UNICORN COLLEGE
Katedra Informačních technologií
Bakalářská práce
Automatizovaný deployment PHP aplikací Automated deployment of PHP applications
Autor práce: Jakub Kohout Vedoucí práce: Ing. Tomáš Holas
2015 Praha
Čestné prohlášení Prohlašuji, že jsem svou bakalářskou práci na téma Automatizovaný deployment PHP aplikací vypracoval samostatně pod vedením vedoucího bakalářské práce a s použitím výhradně odborné literatury a dalších informačních zdrojů, které jsou v práci citovány a jsou také uvedeny v seznamu literatury a použitých zdrojů. Jako autor této bakalářské práce dále prohlašuji, že v souvislosti s jejím vytvořením jsem neporušil autorská práva třetích osob a jsem si plně vědom následků porušení ustanovení § 11 a následujících autorského zákona č. 121/2000 Sb.
V……………… dne …...……..
…….…………………………… (Jakub Kohout)
Poděkování Děkuji vedoucímu bakalářské práce Ing. Tomáši Holasovi za účinnou metodickou, pedagogickou a odbornou pomoc a další cenné rady při zpracování mé bakalářské práce. Dále bych chtěl poděkovat Ing. Václavovi Purchartovi za odbornou konzultaci.
Automatizovaný deployment PHP aplikací Automated deployment of PHP applications
5
Abstrakt První část práce popisuje obecné vlastnosti Continous integration procesu a automatizovaného deploymentu. Druhá část se zabývá praktickým výběrem vhodných řešení, jejich zkombinování a vylepšení pro potřeby malého vývojového týmu, který používá agilní metodiku. Po přečtení této práce by měl být čtenář vybaven teoretickou znalostí Continuous integration procesu a automatizovaném deploymentu. Zároveň by si měl z další části odnést praktický návod, jak oba procesy zavést ve své firmě a vyvarovat se problémům, kterými si musela projít firma, ve které pracuje autor této práce. Klíčová slova: Continous Integration, Automatizovaný deployment, Databázové migrace, Symfony2, Gitlab, Travis, Phing, Webistrano
Abstract First part of this thesis describes common features of continuous integration process and automated deployment. Second part of this thesis is about choosing proper technologies; their coming together and improving them to suit the needs of a small agile development team. After reading this thesis you will have knowledge about continuous integration and automated deployment and be able to implement both processes, without facing the same issues as the author. Keywords: Continuous Integration, Automated Deployment, Database Migrations, Symfony2, Gitlab, Travis, Phing, Webistrano
6
Obsah 1
Úvod............................................................................................................................. 11
2
Continuous integration ................................................................................................. 12
3
2.1
Compile................................................................................................................ 13
2.2
Příprava fixtures ................................................................................................... 13
2.2.1
Centrální testovací databáze ............................................................................ 13
2.2.2
Generování nových fixtures ............................................................................. 14
2.2.3
Centrální testovací databáze a dogenerované fixtures pro testy ...................... 14
2.3
Statická analýza kódu .......................................................................................... 15
2.4
Unit testing ........................................................................................................... 15
2.4.1
PHPUnit [4] ..................................................................................................... 16
2.4.2
Nette\Tester [5] ................................................................................................ 16
2.5
Deploy .................................................................................................................. 16
2.6
Funkční testy a Integrační testy ........................................................................... 16
2.7
Notifikace DevOps .............................................................................................. 16
2.8
Report................................................................................................................... 17
Deployment .................................................................................................................. 17 3.1
Příprava release .................................................................................................... 18
3.2
Verzování aplikací ............................................................................................... 18
3.2.1
Sémantické verzování ...................................................................................... 19
3.3
Manuální deployment .......................................................................................... 19
3.4
Bezvýpadkový deployment.................................................................................. 20
3.4.1
Atomicita ......................................................................................................... 20
3.4.2
Migrace dat ...................................................................................................... 21
3.4.3
Cache soubory.................................................................................................. 22
3.5
Protokoly používané deployment ........................................................................ 22
3.5.1
FTP................................................................................................................... 22
3.5.1.1
Bezpečnost .....................................................................................................................................22
3.5.1.2
Nespolehlivost ...............................................................................................................................23
3.5.2
SCP + SSH ....................................................................................................... 23
3.5.3
RSync [14] ....................................................................................................... 24
3.6 3.6.1
Databázové migrace ............................................................................................. 25 Manuální migrace ............................................................................................ 25 7
3.6.2
Automatické migrace ....................................................................................... 25
3.6.3
Zajištění integrity databáze .............................................................................. 26
3.6.4
Migrace nahoru a dolu ..................................................................................... 27
3.6.5
Zápis migrací ................................................................................................... 28
3.7
Existující software pro deployment ..................................................................... 29
3.7.1
Shell script ....................................................................................................... 29
3.7.1.1
Ukázka jednoduchého deployment scriptu ...................................................................................30
3.7.2
Git hooky [16] .................................................................................................. 32
3.7.3
Capistrano ........................................................................................................ 33
3.7.4
Webistrano ....................................................................................................... 34
3.7.5
Minimální požadavky pro provoz .................................................................... 35
3.8
Existující software pro continuous integration .................................................... 35
3.8.1
Travis CI .......................................................................................................... 36
3.8.1.1
Cena ...............................................................................................................................................37
3.8.1.2
Podpora GIT hostingu ....................................................................................................................37
3.8.1.3
Software as a service .....................................................................................................................37
3.8.1.4
Podpora pro PHP ............................................................................................................................37
3.8.1.5
Podpora dalších služeb a systémů..................................................................................................38
3.8.1.6
Úroveň reportingu .........................................................................................................................38
3.8.1.7
Konfigurace ....................................................................................................................................39
3.8.1.8
Travis CI enteprise ..........................................................................................................................41
3.8.2
GitLab CI ......................................................................................................... 41
3.8.2.1
Podpora GIT hostingů GitLab GitLab ..............................................................................................42
3.8.2.2
Cena ...............................................................................................................................................42
3.8.2.3
Hosting ...........................................................................................................................................42
3.8.2.4
Podpora pro PHP ............................................................................................................................43
3.8.2.5
Podpora dalších služeb a systémů..................................................................................................43
3.8.2.6
Úroveň reportingu .........................................................................................................................43
3.8.2.7
Konfigurace ....................................................................................................................................45
4
Deployovací a CI managment v praxi ......................................................................... 46
5
GitLab .......................................................................................................................... 46 5.1
6
GitLab CI ..................................................................................................................... 47 6.1
7
Instalace ............................................................................................................... 47
Instalace ............................................................................................................... 48
Kompilace pomocí Phingu........................................................................................... 48 8
8
7.1
Proč Phing nemůže dělat kompletní deployment ................................................ 50
7.2
Proč mít build konfiguraci v rámci projektu ........................................................ 50
7.3
Build od nuly oproti inkrementálnímu buildu ..................................................... 51
7.4
Mít Phing nainstalovaný v systému nebo v rámci projektu ................................. 51
7.5
Konfigurace Phingu ............................................................................................. 52
7.5.1
Properties ......................................................................................................... 52
7.5.2
Targets ............................................................................................................. 52
Webistrano ................................................................................................................... 52 8.1
Konfigurace na serveru ........................................................................................ 53
8.2
Konfigurace aplikačního serveru ......................................................................... 56
8.2.1
Zabezpečení privátního klíče ........................................................................... 56
8.2.1.1
Spuštění SSH-Agenta ......................................................................................................................57
8.2.1.2
Automatické spouštění agenta ......................................................................................................57
8.2.1.3
Test, zdali tunelování funguje ........................................................................................................58
8.2.2
Automatické skripty pro založení nové stránky .............................................. 58
8.2.3
Zajištění bezvýpadkového deploymentu [28] .................................................. 59
8.2.3.1
Nginx ..............................................................................................................................................60
8.2.3.2
Apache2 .........................................................................................................................................60
8.3
Vytvoření projektu a dostupná konfigurace......................................................... 60
8.3.1
Vytvoření nového projektu .............................................................................. 61
8.3.2
Stages ............................................................................................................... 65
8.4
Konfigurační volby .............................................................................................. 67
8.4.1
Základní konfigurace ....................................................................................... 67
8.4.2
Symfony2 konfigurace ..................................................................................... 69
8.5
Deployment .......................................................................................................... 69
8.6
Oprávnění a přístupová práva .............................................................................. 71
8.7
Další dostupné příkazy......................................................................................... 72
8.7.1
Rollback ........................................................................................................... 72
8.7.2
Databázové migrace ......................................................................................... 72
8.7.3
Promazání cache .............................................................................................. 73
8.8
Rozšíření specifická pro projekt .......................................................................... 73
8.9
Napojení na NewRelic ......................................................................................... 73
8.9.1
Konfigurace ..................................................................................................... 74
8.9.2
Ukázka ............................................................................................................. 75 9
9
8.10
Definice vlastních šablon a úkolů ........................................................................ 78
8.11
Nedostatky ........................................................................................................... 83
Závěr ............................................................................................................................ 83 9.1
Původní stav ......................................................................................................... 84
9.2
Po implementaci continuous integration a automatizovaného deploymentu....... 84
9.3
Budoucí rozšíření ................................................................................................. 85
10 Conclusion ................................................................................................................... 85 10.1
Original situation ................................................................................................. 86
10.2
After company implemented continuous integration process and automated
deployment....................................................................................................................... 87 10.3
Future extension ................................................................................................... 88
11 Příloha A – Přiložené CD ............................................................................................ 89 11.1
Webistrano ........................................................................................................... 89
11.2
Server scripts........................................................................................................ 89
11.3
Symfony2 Demo .................................................................................................. 89
11.3.1
Fixtures ........................................................................................................ 89
11.3.2
Phing Build .................................................................................................. 89
11.3.3
Testy............................................................................................................. 90
11.3.4
Doctrine Migrations ..................................................................................... 90
12 Seznam obrázků ........................................................................................................... 91 13 Seznam zdrojů.............................................................................................................. 92
10
1 Úvod Programovací jazyk PHP byl původně navržený pro jednoduché webové stránky. Postupem času se z něj stal jeden z nejpopulárnějších jazyků pro webové stránky a s tím narostla mnohonásobně i komplexnost aplikací. Deployment jednoduché webové aplikace o pár zdrojových souborech se dá provést vskutku jednoduše. Na druhou stranu aplikace velkého rozsahu, jejichž zdrojové soubory mají několik tisíc souborů s celkovou velikostí několika set megabytu, které potřebujeme nahrát na několik aplikačních serverů, vyžadují mnohonásobně složitější proces. Pokud aplikace svojí povahou vyžaduje co největší dostupnost a kvalitu, tak celému procesu přidáváme ještě další úroveň komplexnosti. Potřebu pro automatizovaný deployment PHP aplikací dokazuje už jenom to, jaké velké webové portály používají PHP. Na českém internetu se může jednat například o: Slevomat.cz, Csfd.cz, Denik.cz, Uloz.to, Lupa.cz V celosvětovém měřítku jsou ještě mnohonásobně větší portály: Wikipedia.org, Facebook.com, Taobao.com, Flickr.com Automatizovaný a bezvýpadkový deployment PHP aplikací je ale jenom část celého procesu. Jedním z moderních trendů v softwarovém businessu je proces, jemuž se říká continuous integration. Tento proces předchází deploymentu a doplňuje mezery při efektivním vytvářením softwaru. Práce se snaží popsat ideální výběr technologií a zavedení continuous integration procesu ve firmě s následujícími parametry. Tým je malého rozsahu, přibližně 10 lidí. 11
Firma má vlastní serverovou infrastrukturu postavenou na linuxových distribucích. Serverová infrastruktura se skládá z několika aplikačních serverů, tzv. cluster. Firma má všechny aplikace napsané v PHP a aplikačním frameworku Symfony2. Tým má rozsáhlou znalost verzovacího systému GIT. Firma se snaží používat software, který je zdarma, aby minimalizovala náklady. Firma preferuje opensource řešení, před komerčním řešením.
2 Continuous integration Continuous integration (CI), nebo-li méně používáný český výraz „průběžná integrace“ je moderní trend využívaný hlavně agilními týmy. Hlavní myšlenka continuous integration se opírá o tvrzení, že software by měl být po každé změně prověřen, že je spustitelný a funkční. Víceméně to znamená, že se vytvoří build i několikrát denně. Dalším důležitým prvkem continuous integration je rychlé generování výsledků. Čím dříve se vývojáři dozvědí o chybné verzi, tím jednodušší je ji opravit.
1 Jednotlivé kroky CI, Vlastní tvorba
12
2.1 Compile Vývojář připraví změny, vyzkouší si na své lokální stanici, že vše funguje, a odešle commity do vzdáleného repozitáře, kde budou k dispozici ostatním. CI systém stáhne zdrojové soubory do připravené složky. Nainstaluje všechny potřebné závislosti pomocí Composeru a spustí například Phing, který se postará o všechna potřebná konfigurační nastavení.
2.2 Příprava fixtures Většina projektů potřebuje pro svůj běh databázové úložiště. Rozhodně není možné spouštět testy na produkční databázi. To znamená, že je třeba testovací databáze. Existují tři strategie: 2.2.1 Centrální testovací databáze Existuje produkční databáze a testovací databáze, která je odvozená z té původní. Například se data z produkční databáze anonymizují (klíčové údaje se změní na náhodné hodnoty. Například se nahradí jména klientů, čísla kreditních karet apod.) a přenesou do testovací databáze. V momentě, kdy připravuje CI build, tak si tuto databázi zkopíruje. Výhody Nízké náklady na přípravu. Stačí jen zkopírovat databázi a spustit několik UPDATE příkazů pro klíčová data. Máme skoro tu samou databázi na produkci i pro testy, co se týče objemu. Tedy naše testy jsou spouštěny na obdobném počtu dat jako na produkci a můžeme tak připravit výkonnostní testování. Dále máme v testovací databázi případné chyby z minulosti (nekonzistence dat). To má za následek, že testy prověří aplikaci i na nekonzistentní data a máme menší pravděpodobnost, že naše aplikace přestane fungovat produkčním nasazení. Vhodné pro rozsáhlé projekty, které už mají několik let za sebou a tudíž je jejich databáze rozsáhlá a prošla mnoha migracemi. Nevýhody Není dobré v testech spoléhat na data z databáze. Je totiž možné, že tato data jsou neaktuální a testy by mohly být false positive.
13
2.2.2 Generování nových fixtures Při každém spuštění testů se vytvoří databáze dle aktuálního schéma. Pro Symfony projekty s modelovou vrstvou nad Doctrine2 se nejčastěji používá DoctrineFixturesBundle [1]. Pro vytvoření fixures pomocí tohoto nástroje stačí přidat do build scriptu php app/console doctrine:fixtures:load
Užitečným pomocníkem pro generování fixtures je knihovna Faker [2]. Této knihovně předáme název entity, kterou chceme vygenerovat, a kolik jich chceme. Knihovna vygeneruje instance entity a pokusí se uhádnout, jaká data by měla obsahovat. Ukázka tohoto přístupu je k dispozici v příloze 11.3.1 Fixtures.
Výhody Toto řešení má výhody zejména ve fázi, kdy projekt ještě není v produkci a tudíž nepotřebuje řádné databázové migrace. Stačí pokaždé vygenerovat nové schéma a nahrát do něj výchozí hodnoty. Kód je testovaný oproti databázi, která obsahuje opravdu data, proti kterým je napsaný test. Je možné použít například SQLite databázi, pokud je projekt malý a nechceme kvůli tomu zatěžovat databázové servery vytvářením dalších testovacích databází.
Nevýhody Je velice pracné udržovat všechny fixtures aktuální. Obzvláště pro různé konfigurační tabulky v databázi.
2.2.3 Centrální testovací databáze a dogenerované fixtures pro testy Tento způsob je kombinací obou předchozích případů, kdy máme výchozí schéma v podobě vygenerované databáze a do ní dogenerováváme fixtures, které později použijeme v testech. 14
Například systém potřebuje testovat systém objednávek. Nebude tedy spoléhat na to, že už nějaké objednávky v systému jsou, ale vytvoří si nové objednávky a nad těmi spustí testy.
2.3 Statická analýza kódu Statická analýza kódu probíhá tak, že zkoumá kód, jak je napsaný, ale nespouští jej. Většinou zkoumá tyto problémy: Hledání syntaktických chyb (například chybějící závorka, středník apod.). Hledání sémantických chyb (například sčítání čísla a textového řetězce). Chyby vůči specifikovanému coding standartu (například různé formátování kódu). Volání, která nejsou možná pro verzi knihoven, které projekt používá. Bezpečnostní prohřešky (neošetřený vstup / výstup). Volání, která nejsou v definované verzi PHP dostupná (například použití $this v closure v PHP 5.3). Zapomenuté testovací příkazy (nechtěný výpis testovacích proměnných apod.). Detekce „mrtvých“ kusů kódu.
2.4 Unit testing CI systém spustí všechny předepsané unit testy.
Cílem této práce není poskytnout
vyčerpávající informace o unit testingu, proto jen zmíním, jak by měl správný unit test vypadat. Testy by na sobě měly být nezávislé. Testy by měly být spustitelné opakovaně. Unit testy by měly testovat jednu jedinou věc a ta by měla být co nejmenší. Unit test by se měl zaměřit na co nejmenší jednotku a tu otestovat. Pokud má testovaná třída nějaké závislosti, měly by být zamockované. Pro mockování v PHP existuje velká řada nástrojů, jedním z nejznámějších je Mockery [3]. Testy by měly kontrolovat i chybové stavy. V prostředí PHP lze použít následující frameworky pro testování.
15
2.4.1 PHPUnit [4] Nejpoužívanější Framework pro testování na světě v PHP prostředí. Je to robustní Framework, který umí spoustu věcí, což je současně i jeho nevýhoda. Testovací třída musí mít předepsaný formát a musí dědit od konkrétní třídy PHPUnit_Framework_TestCase.
2.4.2 Nette\Tester [5] Český projekt, populární hlavně ve střední Evropě. Hlavními výhodami jsou [6]: Rychlost, protože se scripty pouští paralelně. Testovací skripty jsou samostatně spustitelné soubory.
2.5 Deploy Abychom mohli aplikaci podrobit dalším druhům testů, tak ji nejprve musíme připravit do spustitelného stavu, nebo-li aplikaci nahrát na nějaké dostupné umístění i pro uživatele.
2.6 Funkční testy a Integrační testy Psaní funkčních testů je v Symfony2 frameworku vskutku velice jednoduché. Symfony2 již v sobě obsahuje nástroje pro funkční testy, takže není problém s nimi otestovat např. volání controlleru. Ukázka funkčního a integračního testu je v příloze 11.3.3 Testy.
2.7 Notifikace DevOps Kdy poslat notifikaci je hodně závislé na velikosti týmu, zvolených testech, jejich podrobnosti a úrovni reportingu. Pokud by byla zvolená intenzita notifikací příliš vysoká, tak by DevOps měli tendenci notifikace nečíst a rovnou je archivovat, případně mazat. Příkladem může být, pokud budeme posílat notifikaci o každém provedeném buildu, nezávisle na výsledku testovaní, tak se může stát, že DevOps dostanou stovky emailů denně. V takovém případě by opravdu ve většině případů notifikace nečetli a rovnou je mazali. Což je potom úplně k ničemu, protože mohou smazat i notifikaci, která vyžaduje pozornost. 16
Z mé zkušenosti je nejlepší mít nastavena velmi přísná pravidla na testování, statickou kontrolu kódu a následně zasílat pouze informace o defektních buildech. Pokud máme defektní aplikaci, tak je důležité o tom informovat kompetentní osobu. Kdo je kompetentní osoba záleží na velikosti týmu a rozdělení rolí. Kompetentní osobou může být například ten, kdo poslal do společného repositáře defektní commit, či ten, kdo začlenil defektní větev do další release verze. Nejčastěji jsou notifikace formou emailu, ale je možné zaintegrovat i sofistikovanější systém, například pomocí služeb typu Pagerduty [7]. Pagerduty je služba, která obecně řídí koho notifikovat v případě problému. Hlavní výhoda spočívá v tom, že ví, kdo je nejvhodnější osoba v daný moment pro řešení předem definovaného problému. Například pokud někdo odjede na dovolenou nebo má celý den vytížený schůzkami, tak mu pravděpodobně ani nemá smysl posílat report o nefunkčním buildu. Zároveň PagerDuty uchovává jasný seznam problémů, jejich stav a odpovědnou osobu.
2.8 Report Report je posledním krokem v kolečku „povinností správného CI procesu“. Veškeré výsledky kompilace, testování, uživatelského testování musí být začleněny do reportu o aktuální verzi aplikace. Report by měl být dostatečně podrobný, ale také přehledný, aby se dalo jednoznačně určit, jestli je daná verze v pořádku, nebo obsahuje chyby.
3 Deployment
2 Deployment pipeline, autor: Continuous integration
Jsme v situaci, kdy máme díky CI otestovanou aktuální verzi aplikace a chtěli bychom ji dostat do produkce. Nejprve se podíváme do CI systému, vytáhneme si report na verzi,
17
kterou chceme deploynout. Pokud je report v pořádku, tak můžeme přeskočit k manuálnímu otestování. CI systém by nám měl umožnit vyzkoušet si aplikaci a provést manuální testování. Jak takové testování probíhá, záleží na povaze aplikace a na testovací strategii. Součástí manuálního testování může být například ověření, že grafické rozhraní vypadá dobře a funguje v pořádku. Je to z toho důvodu, že grafická a uživatelská přívětivost se těžko testuje automaticky.
3.1 Příprava release Jedním z best practises pro práci s GITem je práce s větvemi. Tedy vývojář připravuje veškeré změny ve své vlastní větvi a v momentě, kdy je připravena, tak požádá senior vývojáře o code review a o začlenění jeho kódu do vývojové větve. Po začlenění jakékoliv nové změny se správce aplikací1 musí rozhodnout, jestli je změna tak závažná, aby se z ní hned udělal repase, nebo počká na nějaké další změny. Pokud se rozhodne, že připraví nový release, tak pomocí CI serveru ověří, že je aplikace funkční, dělá to, co má, a následně pomocí GIT merge spojí vývojovou větev s tou produkční.
3.2 Verzování aplikací Potřebujeme nějakým způsobem označit různé verze aplikace v přípravě releasu. Do této doby se identifikovaly verze pouze za pomocí hashe commitu (každý commit v GIT repositáři má svůj vlastní unikátní identifikátor označovaný jako „commit hash“). Ovšem je vskutku nepraktické, abychom označovali verze aplikace pomocí tohoto hashe, protože není jasně vidět kontinuita (jenom z pohledu na seznam verzí bychom nevěděli, jak jdou po sobě). Mnohem výhodnější a doporučovaný způsob označování verzí je použití čísel, která se zvyšují s každou verzí. Toto je pravděpodobně nejpoužívanější přístup u většiny aplikací a je k vidění všude okolo nás.
1
Jedná se pouze o roli, klidně do ní může být dosazen opět ten samý seniorní vývojář, který začlenil změny
do vývojové větve.
18
Formát se obvykle zapisuje jako „major.minor.patch[.build]“. Většinou je vidět jen major a minor označení. Patch se drží interně v development týmu. Ovšem například Adobe Flash veřejně uvádí i patch verze, takže příklad verze je 11.2.202.346 [8]. Existují samozřejmě i výjimky, například Linuxová distribuce Ubuntu označuje verze jako year.month z doby vydání. Například tedy verze 14.04 byla vydaná v dubnu 2014. Jde prostě o rozhodnutí firmy.
3.2.1 Sémantické verzování Autorem semantického verzování je Tom Preston-Werner. Tento způsob verzování se zavedl zejména pro opensource projekty, aby bylo jasně rozeznatelné, jak velké změny byly provedeny od poslední verze. Nejdůležitější pravidla jsou: [9] Jakmile je jednou verze publikovaná, tak se její obsah nesmí změnit. Jinými slovy, jakmile uveřejníte verzi, tak už ji nesmíte změnit. Pokud nová verze aplikace obsahuje BC break (backward compatible break neboli porušení zpětné kompatibility), tak se musí zvýšit major verze. Například pokud změníme API nebo upravíme aktuální funkce, tak musíme zvýšit verzi. Pokud nová verze aplikace obsahuje zpětně kompatibilní změnu, tak se musí zvýšit minor verze. Například pokud do API přidáme nějaké nové funkcionality. Patch měníme v situacích, kdy neměníme venkovní chování. Využívá se například na opravu chyb apod. Je třeba dávat pozor na situaci, že i když se nezmění venkovní rozhraní, tak je možné připravit BC break. Může se jednat o situaci, kdy se změní chování aplikace, na které jiná aplikace spoléhala, nebo například opravíme chybu, která je v aplikaci dlouho a ostatní aplikace na to spoléhají.
3.3 Manuální deployment Manuální deployment je prakticky to nejjednodušší, co si můžete představit, prakticky vše se musí udělat vždy ručně. Pro jednoduché aplikace, které obsahují pár souborů, není problém otevřít FTP spojení a nahrát nový soubor na produkční server ručně. Ovšem většina moderních aplikací je značně rozsáhlejších a vyžaduje provedení spousty kroků. 19
Hlavními nedostatky manuálního deploymentu jsou: [10] DevOps tráví čas na rutinních opakujících se úkolech. Je možnost lidské chyby a tudíž i defektní aplikace. Dokumentaci k aplikaci nemusí vždy být aktuální. Na dokumentaci se totiž musí podílet jednak DevOps team, za druhé vývojový tým. Jsme závislí na manuálním testování. Pokud DevOp zapomene něco vyzkoušet, tak aplikace může být defektní. Obvykle máme více prostředí (vývojové, testovací a produkční) a aplikace má své vlastní specifické nastavení pro každé z nich. Manuální deployment obvykle provádí jedna osoba, která má zkušenosti a znalosti o dané aplikaci, prostředí a postupu. Pokud tato osoba má dovolenou nebo ukončí svoji činnost ve firmě, firma je v problému. Nový člen vývojového týmu má mnohonásobně více práce s rozběhnutím projektů jen za pomoci dokumentace. Otestovat manuální deployment jde pouze tak, že to celé vyzkoušíme. Otestovat automaticky deployment jde levně a rychle. Manuální deployment není skoro vůbec auditovaný a je obtížné hledat případný problém.
3.4 Bezvýpadkový deployment Managment firmy obvykle vyžaduje, aby aplikace běžela nonstop bez výpadku a pravděpodobně nebude ochotný tolerovat několika minutové výpadky vždy, když se správce aplikací rozhodne odeslat novou verzi aplikace do produkčního prostředí. 3.4.1 Atomicita Atomicita, jinými slovy nedělitelnost, znamená, že se nějaká činnost buďto povede celá, nebo nepovede vůbec. Neexistuje žádný stav mezi tím. Webová aplikace potřebuje pracovat na verzi 1 nebo na verzi 2, ale rozhodně není schopná fungovat, pokud by měl k dispozici pouze polovinu souborů potřebných k běhu. V takovém případě riskujeme, že aplikace bude nekonzistentní, nebude fungovat a může dojít i k trvalé ztrátě dat. 20
Jedním z možných řešení je novou verzi nahrát do jiné složky na serveru a v momentě, kdy je vše připraveno, tak přepnout webový server do této nové složky.
3.4.2 Migrace dat Při migraci dat, či změně databázového schéma existuje riziko, že deployment klidně na několik hodin zamkne klíčové databázové tabulky a aplikace bude po celou tu dobu absolutně nedostupná. Například pokud aplikace loguje každé uživatelské přihlášení do databáze do speciální tabulky a vývojář, či databázový specialista se rozhodne, že přidá do nové verze aplikace migraci, která změní typ jednoho sloupečku, tak na vývojové či testovací databázi migrace proběhne rychle, protože tyto databáze mají obvykle jenom několik tisíc záznamů o přihlášení uživatelů. Bohužel pokud není součástí continuous integration procesu i výkonnostní testování, tak zajistíme problém s touto migrací až v produkčním prostředí, kdy se pokusíme provést deployment této migrace nad miliardami záznamů. Vzhledem k povaze daného požadavku změnit typ sloupce a množství záznamů dojde k uzamknutí tabulky pro zápis a žádný z klientů se již nepřihlásí, dokud tato migrace nedoběhne. Při přípravě migrací si musí být databázový specialista velice jistý tím, co dělá, a není na škodu zaimplementovat výkonnostní testování do continuous integration procesu. Samozřejmě není vždy možné se vyhnout složitějším migracím a potom je třeba zajistit plánovanou odstávku systému. Existuje i řešení, jak zajistit bez výpadkovou migraci za předpokladu, že máme dvě synchronizované databáze vedle sebe a podporují transakční zpracování. Aplikace komunikuje pouze s databází č. 1, v tento moment zastavíme synchronizaci mezi databází č. 1, č. 2 a veškeré transakční logy začneme ukládat například do souboru. Na databázi č. 2 spustíme potřebnou migraci a počkáme, než doběhne. V momentě, kdy migrace doběhne, tak aplikujeme všechny uložené transakční změny na databázi č. 2 a přepneme na ni veškerý provoz. Následně jen sesynchronizujeme obě databáze s tím, že databáze č. 2 je označena jako ta hlavní.
21
3.4.3 Cache soubory Velké aplikace obvykle používají nějaké dočasné úložiště pro často používaná data či výpočty, které jsou časově náročně, aby je nemusely vždy znovu získávat. Problémem je to, že pokud provedeme deployment nové verze aplikace, tak nikdo nemůže zaručit, že se ten výpočet nezměnil. Tudíž je vhodné všechna úložiště s těmito typy dat okamžitě promazat. Proto je nutné, aby aplikace či úložiště těchto dat vystavily ven nějaké API, které to umožní. Zároveň je také nutné počítat s cache úložištěm, které nemusí být pod naší kontrolou. Například se může jednat o různé CDN sítě, či cache na straně klienta. Zejména se tento problém řeší u statických souborů, které posíláme klientovi. Je proto vhodné vždy statické soubory minifikovat1 a jako název výsledného souboru použít hash obsahu, tím zajistíme, že klient vždy dostane aktuální verzi.
3.5 Protokoly používané deployment 3.5.1 FTP Tento způsob je z hlediska historie jedním z nejznámějších a dodnes hojně využívaným. Výhoda tohoto řešení je jeho jednoduchost. Protokol FTP byl navržen v roce 1985 [11]. FTP využívá pro svůj běh dva porty, po jednom posílá řídící signály a na druhém portu posílá data. Jedná se o port 20 a 21, konkrétní využití těchto portů záleží na nastavení.
3.5.1.1 Bezpečnost Největším problémem tohoto protokolu je bezpečnost, ve standardech FTP protokolu RFC 2577 [12] jsou tyto problémy zmíněny.
1
Minifikace je proces, kdy se snažíme zmenšit objem dat o nepotřebná data. Například při minifikaci
javasciptu se z kódu vypustí všechny nepotřebné mezery, komentáře, nové řádky apod. Zároveň se několik souborů spojí do jednoho jediného a to ušetří rychlost načtení těchto dat v momentě, kdy si o ně klient požádá.
22
Konkrétně se jedná o tyto útoky: Brute force attacks Bounce attacks Packet capture (sniffing) Port stealing Spoof attacks Username protection Pravděpodobně ten nejnebezpečnější spočívá v útoku „packet capturing“, což se dá volně přeložit jako „odposlouchávání paketů“. Útok využívá toho, že FTP není šifrovaný protokol a útočník může odposlechnout jednak samotná data, tak jméno a heslo, pomocí kterého se potom může přihlásit na server a udělat škodu. Tuto zranitelnost řeší protokol sFTP popřípadě SCP, jež bude zmiňován dále.
3.5.1.2 Nespolehlivost Protokol FTP funguje dobře, pokud se serverem pracuje vždy jeden uživatel. Bohužel toto v reálných podmínkách není možné zařídit a obvykle se na server pojí mnoho uživatelů současně. V takovémto momentě protokol přestává být spolehlivý. Obzvláště při nahrávání velkého počtu souborů se zvyšuje šance, že nějaký soubor selže a vývojář potom bude velice složitě dohledávat soubor, který se nezkopíroval celý [13]. Z těchto důvodů není vhodné používat pro deployment protokol FTP. Bohužel v mnoha případech se jedná o jedinou metodu, obzvláště pokud potřebujete jednoduchý a levný webhosting.
3.5.2 SCP + SSH SSH je protokol pro vzdálený přístup k příkazové řádce na serveru. SCP je protokol pro přenášení souborů po SSH spojení. Obrovská výhoda této metody je spolehlivost a bezpečnost (veškerá data i příkazy jsou šifrovány).
23
Díky tomu, že je možnost se přihlásit přes SSH, tak není problém měnit obsah souborů na vzdáleném serveru, využívat symlinky a další pokročilé metody. Jenom samotné využití daného protokolu by byla ruční metoda, ale díky výhodám tohoto protokolu jej později budeme potřebovat v automatizovaných postupech jako jednu součást. Nevýhoda tohoto řešení spočívá v tom, že administrátor serveru obvykle nechce dávat SSH přístup zákazníkům, protože ti jednak získávají pohodlí s prací na jejich aplikaci, ale na druhou stranu přináší velké riziko, že neodborným zásahem způsobí škodu na samotné konfiguraci serveru (smazáním důležitého souboru, složky aj.). Tímto se dostáváme k dalšímu problému a tím je pro vývojáře pokročilá znalost serverového prostředí. Na serveru není žádné grafické prostředí a vývojář je odkázán jen na příkazovou řádku.
3.5.3 RSync [14] RSync je protokol, který je navržen na synchronizaci souborů po síti. Je navržen jako náhrada za protokol SCP. Obrovská výhoda tohoto protokolu spočívá v tom, že se přenáší jen změny a nikoliv všechny soubory znovu. Uvedu příklad, za použití SCP by se všechny zdrojové soubory musely vždy znovu všechny nahrávat na server. To může být klidně i stovky megabytů a pro síť by to bylo velice zatěžující. Naopak RSync se podívá, jaké soubory se liší od těch na serveru, a nahraje jen tyto změněné soubory. Výhoda tohoto postupu spočívá v nízké režii na síti, ale problémem může být rollback. Pokud vývojář nahraje špatnou verzi aplikace nebo něco jiného selže, potřebuje se co nejrychleji vrátit k předchozí verzi. Což v tomto případě znamená, aby si ve verzovacím nástroji stáhl aktuální verzi a tu opět nahrál na server, což může zabrat klidně desítky minut u větších změn. Tedy desítky minut, kdy je aplikace zcela nefunkční.
24
3.6 Databázové migrace Většina aplikací potřebuje někam ukládat data. Obvykle proto jako úložiště dat používá databázi. Problém je v tom, že i databázové schéma a data se postupem času musí měnit spolu s aplikací. Aplikaci máme ve verzovacím systému a můžeme se tedy kdykoliv vrátit k jakékoliv verzi. Musíme tedy ještě do verzovacího systému dostat databázové schéma.
3.6.1 Manuální migrace Nejprimitivnější implementace migrací je nějakým způsobem sdílet sql příkazy. Sdílení může být za pomoci dokumentace nebo verzovaných souborů s SQL dotazy v repositáři. Jediná výhoda tohoto řešení je asi jen prakticky nulová investice do přípravy prostředí pro migrace. Nevýhody manuálních migrací: Musíme uchovávat v dokumentaci seznam již aplikovaných migrací, jinak nebudeme vědět, které migrace ještě chybí aplikovat. Extrémně náchylné na lidskou chybu. Pokud vývojář špatně připraví migraci, případně ji vůbec nevytvoří, tak vzniká chyba, která se pravděpodobně odhalí až při deploymentu do cílového prostředí. Pro manuální migrace není možné připravit testy. Není možné tento proces zautomatizovat a zahrnout jej do continuous integration procesu. Není možné takové migrace testovat. 3.6.2 Automatické migrace Pro automatické migrace je vhodné využít existující knihovnu. Výhody automatické migrace: Nemusíme se starat o to, které migrace už byly aplikovány a které ne. Knihovna může generovat migrační skripty automaticky. Například porovnáním schéma databáze a ORM schéma v aplikaci. Bohužel to nikdy není ultimátní řešení, vygenerované skripty stejně musíme projít ručně a finálně upravit. Automatické migrace je možné zahrnout do continuous integration procesu a tím pádem mít i automatické testy. 25
Informace o provedených migracích je možné ukládat do tabulky v databázi. Výhoda tohoto způsobu je v tom, že databáze ví, v jakém je stavu, bez toho, aby měla přístup k souborovému systému. Nevýhoda tohoto postupu je v tom, že musíme mít aktivní připojení do databáze pro zjištění, jestli nechybí nějaká migrace. Transakce a z části i naše migrace se opírají o princip ACID, což je akronym následujících slov. Atomic – Atomicita, každá migrace se buďto provede úplně celá bez chyb, nebo se neprovede vůbec. Toto je věc, kterou musíme v migracích řešit a je detailně popsána v následující kapitole. Consistent – Konzistence, data po provedení migrace neporušují žádná integritní pravidla našeho schéma. Pokud by porušovala, tak se migrace nesmí dokončit a musí skončit s chybou. Isolated – Izolované, jednotlivé migrace nesmíme spouštět paralelně, ale vždy je musíme spouštět za sebou. Durable – Provedená migrace musí být trvale zapsaná v databázi i kdyby celý systém přestal fungovat hned po provedení migrace. Toto je převážně záležitost databáze, v migracích je jen potřeba zajistit, že informace o aplikované migraci je aktualizována ve stejné transakci. 3.6.3 Zajištění integrity databáze Jedna migrace se obvykle skládá z 1 až N dotazů do databáze. Není možně vždy napsat celou migraci do jednoho databázového dotazu. Pokud ale v rámci jedné migrace máme více než jeden dotaz, tak musíme nějak zajistit, že se buďto provede celá migrace, nebo ne. V žádném případě se nesmí stát, že se provede polovina dotazů a druhá polovina dotazů skončí s chybou. V takovém případě by migrace mohla mít fatální následky. Například pokud bychom chtěli přesunout data a transformovat je do jiné tabulky, tak musíme položit minimálně dva dotazy do databáze. První dotaz je zkopírování dat a jejich transformace do druhé tabulky. Druhý dotaz smaže původní data.
26
Pokud napíšeme transformační dotaz s chybou, tak přijdeme o všechna data, protože se neprovede první dotaz na zkopírování a druhý dotaz, který bude následovat, data nenávratně smaže. Tomuto problému se dá zabránit tak, že pokud nějaký dotaz skončí chybou, tak by migrace měla vyhodit výjimku a nepokračovat dál. Výjimka nám ovšem řeší jenom polovinu problému. Následující příklad popíše problém, který výjimka neřeší. Chceme připravit novou tabulku, která bude obsahovat konfigurační nastavení naší aplikace. Musíme tedy připravit dva dotazy. V prvním dotazu vytvoříme tabulku a v druhém ji naplníme. Pokud se povede vytvořit tabulku, ale nepovede se vložit data, tak s největší pravděpodobností nebude fungovat zbytek aplikace, protože se provedla pouze část migrace. Výjimka sice vyskočila, ale první dotaz už se provedl. Řešením tohoto problému je použití databázových transakcí. Transakce funguje tak, že databázi řekneme „Begin transaction“ („začínám transakci“), pak posíláme dotazy, které se sice aplikují ale jenom v rámci tohoto připojení. V momentě, kdy jsou všechny dotazy provedeny, tak migrace pošle „Commit“ („hotovo“), až teď databáze aplikuje všechny předcházející dotazy a jsou trvale uloženy v databázi. Pokud by jakýkoliv dotaz skončil chybou a byla vyhozena výjimka, tak musí migrace poslat „Rollback“ („vrať změny zpátky“). Databáze v takovém momentu zahodí veškeré poslané dotazy a tváří se, že se nic nestalo. 3.6.4 Migrace nahoru a dolu Pokud se řeknou migrace, tak si většina lidí představí pouze aktualizaci databáze směrem nahoru, tedy aktualizaci na novější verzi. Problém ovšem je, že občas musíme jít i zpět a nemusí jít jenom o fatální důvody typu rollbacku celé produkční aplikace. Kupříkladu pokud vývojový tým drží pro každý nový use case vlastní větev ve verzovacím systému, tak vývojáři obvykle mění aktuální větve velice často. Pokud se chce přepnout z jedné feature větve do druhé, tak musí nejprve vrátit stav databáze do společného momentu obou větví a až potom aplikovat nové migrace.
27
K tomuto je právě vhodné v každé migraci definovat cestu nahoru, tedy aktualizace, a pak také cestu zpátky, jak dané aktualizace vzít zpět. S tímto ovšem přichází řada problémů se zpětnou kompatibilitou. Obzvláště napsat migraci tak, aby šla vždy vrátit, je hodně těžké. Zde je popis několika situací, které mohou nastat v cestě nahoru a jak k nim správně zapsat cestu zpět. Mazání dat – tohle je relativně jednoduchá úloha, při cestě nahoru je nemazat, ale jen přesunout do nějaké dočasné tabulky. V migraci dolu zase naopak přesunout data z dočasné tabulky to té správné. Pozor na problém s UNIQUE sloupečky.1 Aktualizace dat - pokud měníme data na nějakou konkrétní hodnotu, tak nám nezbude nic jiného než opačný dotaz zapsat do migrace na cestě dolu. Toto funguje pouze pro omezené množství změn, pokud bychom například měnili data způsobem, že by tento krok již nešel vrátit zpět, tak je musíme při cestě nahoru zapsat do nového sloupečku a všechna data zkopírovat. Změna schéma databáze – tohle může být datově nejnáročnější úkol, pokud potřebujeme nějaký sloupeček smazat, tak musíme zálohovat prakticky celou tabulku. V případě, že chceme sloupeček přidat, tak při cestě dolu jej zase můžeme odebrat, zde je třeba se několikrát ujistit, jestli opravdu ta data v mazaném sloupečku nepotřebujeme. V žádném případě se nejedná o úplný výpis problémů, ale o velice jednoduchou ukázku, že napsat správně databázové migrace není vůbec jednoduchý úkol. 3.6.5 Zápis migrací Jak zapsat migraci záleží na použité knihovně, může se jednat o textový soubor s příponou sql nebo se může jednat o třídu v PHP. Sql soubor nabízí pouze velice omezené možnosti, obvykle se zapisuje pouze migrace nahoru, nikoliv dolu. Mnohem propracovanější migrace nabízí Doctrine Migrations. Ukázka jak řesit migrace pomocí doctrine migrations je v příloze 11.3.4 Doctrine Migrations.
1
Mezi tím než spustíte migraci dolů, tak se objeví nová data v původní tabulce. Tudíž při přesunu dat zpátky
do produkční tabulky, může nastat situace, že už tam je řádek se stejným UNIQUE klíčem, který se snažíte vložit.
28
Jak je vidět z ukázky, migrace umožňují obě formy cest. Každá migrace se zapisuje jako samostatná třída. Důvodem, proč použít Doctrine Migrations, je (pokud používáte Doctrine jako ORM) možnost porovnávat aktuální schéma databáze oproti entitám a vygenerovat z toho migraci. Samozřejmě je možné pouze vygenerovat migraci směrem nahoru a nikoliv dolu. Alternativa k Doctrine Migrations je například projekt Phinx [15]
3.7 Existující software pro deployment Různých knihoven a softwaru existuje hodně. Není jeden nejlepší, ale každý se hodí na něco jiného. Kritéria pro výběr správného nástroje pro deployment: Počet projektů – čím více projektů máte, tím by měla být větší páka k tomu požít automatické řešení. Velikost týmu – pro dva lidi v týmu nemusíme řešit bezpečnost tak jako pro 50 lidí. Počet serverů – pro jeden server je mnohonásobně jednodušší provést deployment než pro cluster skládající se z několika serverů. Technologie projektu – nemá smysl se pokoušet deploynout aplikaci napsanou v Javě pomocí nástrojů, které nativně podporují PHP či Ruby On Rails. Serverová platforma – software pro deployment musí být kompatibilní s operačním systémem, který provozujeme na serveru. Serverové prostředí – pokud už na serveru používáme technologii pro konfigurační management typu Chef nebo Puppet, tak stojí za zvážení, jestli jej nepoužít pro deployment aplikací místo hledání další aplikace. 3.7.1 Shell script Shell script je pravděpodobně ta nejjednodušší forma automatizovaného deploymentu. Implementace může být formou primitivního scriptu, který jen zkopíruje zdrojové soubory z repozitáře do složky, kam je směrovaný virtualhost webového serveru. Naopak je možné mít i velice komplexní script, který nejprve celý projekt otestuje, provede statickou analýzu kódu, rozkopíruje jej na všechny servery, spustí kompletní build a spustí databázové migrace.
29
Vzhledem k tomu, že nejsou vymezeny žádné hranice a záleží jenom na tom, kolik je tým ochotný investovat energie do přípravy deployment scriptů, tak není možné aplikovat standardní kritéria na tento typ projektu. Teoreticky není ani nutné, aby se jednalo o Shell script, může být napsán v jakémkoliv jazyce, záleží jen na technologii, co je k dispozici na serveru. Výhoda shellu spočívá v tom, že je nativní na Linuxovém operačním systému, nemá omezení na dobu běhu scriptu a je mnohonásobně rychlejší než třeba PHP. Pro zjednodušení ale uvádím jako název „Shell script“. Výhody shell skriptu: Oproti ručnímu přístupu značně eliminujeme riziko lidské chyby. Obrovská rozšiřitelnost. Script může provádět prakticky cokoliv, co si naprogramujeme. Nejsme vázáni na technologii. Můžeme použít jakýkoliv interpret, který je k dispozici. Nevýhody shell skriptu: Prakticky vše si musíme naprogramovat, případně pospojovat kusy kódu, které nalezneme na internetu. Neexistuje grafický výstup. Návrh toho scriptu musí provést zkušený odborník, jinak se vystavujeme riziku, že bude deployment sice funkční, ale bude mít nečekané vedlejší efekty (například bude špatně zálohovat nebo bude deployment vždy s nepatrným výpadkem).
3.7.1.1 Ukázka jednoduchého deployment scriptu Předpokládá tuto strukturu složek * home ** project – domovská složka projektu *** update – složka, která obsahuje všechna potřebná data pro deployment **** update.sh – script který provádí deployment **** repository – dočasná složka, kam se kopírují zdrojové soubory z repozitáře **** backups – složka, která obsahuje zálohy minulých verzí *** www – domovská složka pro samotný projekt
30
Ukázkový script provádí tyto operace: Vytváří zálohu aktuální verze aplikace Aktualizuje aplikaci Instaluje závislosti pomocí Composeru Spouští databázové migrace Zasílá notifikaci NewRelic o provedeném deploymentu.
Update.sh #!/bin/bash # exports current version from GIT repository echo Cloning repository cd /home/project/update/repository; git pull origin master; echo OK #current files backup echo Backing up files filename=back_$(date +%Y%m%d) tar –cvzf /home/project/update/backups/$filename /home/project/www echo OK # uses rsync to copy the new version to the production environment echo Synchonizing production dir with current master branch ... rsync -r -t -v -u /home/project/update/repository/* /home/project/www echo OK echo Install dependencies via composer cd /home/project/www && composer install --no-scripts --verbose --prefer-dist --no-dev echo OK echo Running Database Migrations php /home/project/www/bin/console "Doctrine|Migrations|migrate" echo OK echo "Sending notification to New Relic" curl -H "x-api-key:INSERT_YOUR_KEY " -d "deployment[app_name]=PROJECTNAME" https://rpm.newrelic.com/deployments.xml echo Project update completed
31
3.7.2 Git hooky [16] GIT umožnuje mít několik různých verzí aplikace vedle sebe, označuje se to jako branch neboli větev. GIT hook deploy funguje na tom principu, že na serveru máme větev production a na ni máme navěšený tzv. hook. Hooků je několik, ale pro deployment nás zajímá konkrétní post-update. Pokaždé, když se na server do větve production nahraje nová verze (nový commit), tak se spustí právě tento hook, což je uložený script. Daný script už může být ten samý, jako jsme uvedli v kapitole 3.7.1.1 Ukázka jednoduchého deployment scriptu.
Automatizovaný script
Repozitář zdrojových kódů
Produkční server
vá No ve r ze a lik ap ce Vývojář
3 Schéma nasazení aplikace pomocí GIT hooku, zdroj: vlastní tvorba
32
Využití GIT hooku má téměř ty samé nedostatky jako shell skript, ale přináší řadu výhod. Automatizace – není třeba se přihlašovat na vzdálený server a ručně spouštět script, čímž se vystavujeme riziku, že osoba provádějící deployment udělá chybu. Jednoduchá možnost deploymentu jakéhokoliv commitu – bez toho abychom nějakým způsobem manipulovali s konfigurací na serveru, můžeme provést deployment jakéhokoliv commitu. Rychlý ale stále rizikový rollback – pokud potřebujeme rollback, tak stačí vzít jiný commit a provést jeho deployment. Musíme ovšem pamatovat na riziko spojené s databázovými migracemi. Osoba, která provádí deployment, nemusí mít přístup na server – u málo kritických projektů, či u testovacích projektů, nemusíme vytvářet přístupy na aplikační servery například pro externisty, kterým chceme dát možnost deploymentu, ale nikoliv aby měli přístup do VPN či přímo na server. Přehled o tom, jaká verze je aktuálně v produkci – jednoduše z GITu zjistíme, jaká verze je aktuálně na serveru a kdo ji tam dal.
3.7.3 Capistrano Capistrano je pokročilý nástroj pro nasazení softwaru na server. Jedná se o konzolovou aplikaci, která je nainstalována na počítači vývojáře, či serverového správce. Klíčovou součásti jsou tzv. recepty, což jsou předpřipravené skripty, kterými nahráváme aplikaci na server. Recept může být například „deploy“, provést migrace na databázi, restartovat cache apod.
33
Repozitář zdrojových kódů
Zd ro jo vé
s Na
kó dy
az
uk od r íp en
e ív čn
í testova N a s a ze n
rz
e
Produkční server
cí verze Testovací server
Capistrano
Spouští recepty Vývojář 4 Schéma nasazení aplikace pomocí Capistrana, zdroj: vlastní tvorba
Nevýhoda tohoto řešení spočívá v tom, že vývojář musí mít na svém počítači nainstalováno Capistrano, musí s ostatními sdílet recepty a vše je třeba řešit přes příkazovou řádku. Zároveň také musí mít sám přístup na všechny servery a oprávnění ke spuštění všech příkazů v receptu, čímž se firma vystavuje bezpečnostnímu riziku. 3.7.4 Webistrano Webistrano je grafická nástavba nad Capistranem. Webistrano byl projekt založený a vyvíjený společností Peritor consulting. Firma byla odkoupena společností Amazon AWS, která se rozhodla nadále nerozvíjet tento nástroj pro deployment, i přestože se jedná o jeden z nejpoužívanějších nástrojů pro deployment (GitHub 20. 4. 2015 ukazuje 278 forků). Naštěstí Webistrano je pouze grafická nástavba nad stále aktuálním projektem Capistrano a doplněna o několik dalších knihoven pro rozšíření podpory. 34
Samotné Webistrano má pouze podporu pro Ruby on Rails a nikoliv podporu pro PHP projekty. Podpora pro projekty postavené nad PHP lze přidat začleněním projektů třetích stran, jako je například Capifony, případně je nutné dopsat si rozšíření samostatně. 3.7.5 Minimální požadavky pro provoz Projekt vyžaduje Linuxový server, popřípadě OS X server. Windows není podporovaný. Dále je potřeba na serveru mít nainstalované tyto knihovny: Ruby verze 1.8.7 nebo 1.9.3 (verze 2.0.0 a vyšší nejsou podporovány) Rubygem verze 1.6.2 SQL databáze – MySQL / PostgreSQL GIT Detailní popis je k nalezení v kapitole 8 Webistrano.
3.8 Existující software pro continuous integration Continous integration jako knihovna, či jako samostatně běžící software by měl umožňovat provedení všech kroků, tedy od kompilací buildu, přes testy, až po vygenerování reportu. Většina aplikací to umí, ovšem s rozdílnou mírou podpory a komplexnosti celkově.
35
Hlavní kritéria pro výběr Continous integration serveru: Cena. Podpora GIT hostingu. Pokud hostujete repozitáře v GitLabu nebo Bitbucketu, tak nebudete mít k dispozici všechny CI servery. Jestli potřebujete hostovat CI server u sebe na serveru, například kvůli bezpečnosti nebo vám nevadí spolehnout se na „cizí“ servery. Podpora programovacího jazyku. Pokud daný CI server nenabízí podporu vašeho programovacího jazyka, tak nejspíš nebude ten vhodný. Podpora dalších služeb. Moderní aplikace obvykle závisí na dalších externích systémech, se kterými komunikují pomocí API. Je třeba, aby tyto systémy byly k dispozici i v testovacím prostředí na CI serveru. Například se může jednat o message brokera RabbitMQ či o různé typy databází. Úroveň reportingu. Například takový Jenkins má mnohonásobně propracovanější report než třeba GitLab CI. Počet různých rozšíření. Pro doplnění chybějící funkcionality. Rozšiřitelnost. Zda-li je možné systém doplnit o dodatečné funkcionality.
3.8.1 Travis CI Travis je pravděpodobně jeden z nejznámějších CI serverů pro PHP. Jedná se opensource projekt, skládající se momentálně z těchto částí [17]: travis-api travis-build travis-core travis-cookbooks travis-hub travis-listener travis-logs travis-support travis-tasks travis-web travis-worker 36
3.8.1.1 Cena Travis je k dispozici zdarma pro open source projekty na adrese http://travis-ci.org. Placená verze pro skryté repozitáře (není k nim přístup bez authentizace a autorizace) je k dispozici na adrese http://travis-ci.com. Cena se odvíjí od počtu pracovních instancí, které mohou běžet ve stejnou dobu. Například pokud víme, že pro provedení celého kolečka CI buildu potřebujeme 10 minut a během běžného pracovního dne náš tým vyprodukuje 150 commitů, tak bychom vygenerovali takové množství práce, které by jedna pracovní instance zpracovávala 25 hodin čistého času. To by znamenalo, že náš tým bude ustavičně čekat na CI report. Pro takový tým by bylo optimální mít přibližně 5-10 pracovních instancí.
3.8.1.2 Podpora GIT hostingu Bohužel Travis podporuje pouze repozitáře, které jsou hostované na GitHubu a není možné použít jiný systém. Momentálně se ani neplánuje budoucí podpora pro další systémy jako je Bitbucket [18] apod.
3.8.1.3 Software as a service Travis je primárně poskytovaný jako SaaS (software as a service), tedy nepotřebujete vlastní server, protože je Travis provozovaný na jejich serverech. To má obrovskou výhodu v tom, že se nemusíte starat o aktualizace, dostupnost služby apod. Nevýhoda spočívá v tom, že se musí platit měsíční poplatky za pronájem služby. Další nevýhoda spočívá v bezpečnosti, protože vaše zdrojové kódy budou k dispozici třetí straně.
3.8.1.4 Podpora pro PHP Travis nabízí širokou paletu verzí PHP, dokonce je k dispozici i ještě nevydané PHP7 a nightly build PHP. Co vidím jako velkou výhodu Travisu je, že umí otestovat jeden build vůči několika různým verzím PHP. Toto se hodí zejména při přípravě knihoven, u kterých nevíme, kdo všechno je použije.
37
3.8.1.5 Podpora dalších služeb a systémů Pro každý build se startuje virtuální systém, který není sdílený s nikým dalším, tzn. je určený pouze pro tento build [19]. Toto řešení má nevýhodu v rychlosti, protože nastartování instance chvilku trvá. Ale na druhou stranu obrovská výhoda je, že je možnost instalace čehokoliv. Například Travis má momentálně podporu pouze pro MySQL 5.5, pokud chceme novější verzi, tak si ji musíme sami doinstalovat. Ale to není vůbec žádný problém. V samotném základu má Travis aktuálně podporu pro tyto služby [20]: MySQL PostgreSQL MongoDB CouchDB Redis Riak RabbitMQ Memcached Cassandra Neo4J ElasticSearch Kestrel SQLite3
3.8.1.6 Úroveň reportingu Travis v základní konfiguraci posílá notifikaci pomocí email kompetentní osobě v těchto případech: Pokud je daný build defektní a testy neproběhly úspěšně. Pokud byl build defektní a nyní je už opravený.
38
Travis se neomezuje jenom na email, umožňuje posílat notifikaci skrz tyto kanály [21]: Email IRC Campfire Flowdock HipChat Sqwiggle Slack Webhook Co se týče složitějších reportů, například graf úspěšnosti buildů, to Travis momentálně neumí. Travis obecně neumí generovat žádné grafické výstupy, hlavní výstup je pouze textový záznam o proběhnutém buildu. Tato funkcionalita se obvykle doplňuje službami třetích stran, například pro code coverage lze použít Coveralls [22].
3.8.1.7 Konfigurace Veškerá konfigurace se provádí pomocí souboru „.travis.yml“, který je umístěn v kořenovém adresáři daného repozitáře. Pomocí tohoto souboru jsme schopni kompletně připravit celý build, aniž bychom museli sáhnout do potenciální webové administrace. Travis totiž ani žádnou administraci projektů nemá.
39
Zde je ukázka konfigurace pro Nette projekt [23] language: php php: - 5.3.3 - 5.4 - 5.5 - 5.6 - hhvm env: - TESTER_PHP_BIN="php-cgi" - TESTER_PHP_BIN="hhvm" matrix: allow_failures: - php: hhvm exclude: - php: 5.3.3 env: TESTER_PHP_BIN="hhvm" - php: 5.4 env: TESTER_PHP_BIN="hhvm" - php: 5.5 env: TESTER_PHP_BIN="hhvm" - php: 5.6 env: TESTER_PHP_BIN="hhvm" - php: hhvm env: TESTER_PHP_BIN="php-cgi" services: - redis-server before_install: - composer self-update install: - composer install --no-interaction --prefer-source before_script: - mysql -u root -e 'CREATE DATABASE testbase;' - mysql -u root testbase < tests/testbase.sql script: - ./vendor/bin/tester -p $TESTER_PHP_BIN -c ./tests/php.ini -s ./tests/ after_failure: # Prints *.actual files content - for i in $(find ./tests -name \*.actual); do echo "--- $i"; cat $i; echo; echo; done
40
Jak je vidět z ukázky, tak se soubor „.travis.yml“ skládá z několika částí [24]: language, php, matrix – konfigurace prostředí a testů services – jaké služby se mají spustit (databáze apod.) before_install – zde nastavujeme systém a jeho závislosti install – instalace potřebných služeb before_script – nastavení přístupu do databáze, konfigurace testů apod. script - jediný povinný krok, zde se provádí samotné testy after_success or after_failure – co se má stát v případě testů, když (ne)projdou after_script – vždy po doběhnutí testů
3.8.1.8 Travis CI enteprise Na konci roku 2014 byla představena Enterprise edice. Největší změna oproti klasickému Travisu je možnost hostovat si Travis sám na vlastním serveru. Travis Enteprise je distribuovaný pomocí Dockeru. Dockeru věnuji celou jednu kapitolu v této práci, proto jej zde nebudu detailně popisovat. Bohužel Travis CI Enterprise je stále pevně svázaný s GitHubem, popřípadě GitHub Enteprise edicí. Z toho vyplývá, že není možné integrovat Travis s jiným GIT uložištěm než je GitHub. Cena na oficiálních stránkách bohužel není uvedena a jedná se o individuální domluvu. 3.8.2 GitLab CI GitLab CI je úzce spojený s GitLab HQ. GitLab CI Je open source projekt postavený na Ruby on Rails na architektuře master – workers.
41
5 Topologie GitLab CI, zdroj: oficiální stránka GitLab CI https://about.gitlab.com/gitlab-ci/
Tuto topologii používá také Travis, ale tam to nevidíme, protože to nemusíme vůbec řešit. Máme tedy CI server, který má webové rozhraní a jeho úkolem je dávat práci ostatním aplikacím. Jednotlivé dílčí aplikace se nazývají „Runner“ a jejich úkolem je vždy vykonat pouze jeden úkol, poslat výsledek CI serveru a ukončit svoji činnost.
3.8.2.1 Podpora GIT hostingů GitLab GitLab GitLab CI je úzce propojený s GitLab HQ, aktuálně podporuje tedy pouze toto úložiště.
3.8.2.2 Cena GitLab CI je open source projekt a je zdarma.
3.8.2.3 Hosting GitLab CI je plně pod vaší kontrolou a můžete jej hostovat na vašich serverech. Tudíž je možné nepustit vůbec GitLab CI do internetu. GitLab nabízí i alternativu v podobě hostované verze na https://gitlab.com/users/sign_in, která je také zatím zdarma.
42
3.8.2.4 Podpora pro PHP Vzhledem k tomu, že GitLab musíte hostovat na svém serveru, tak je podpora pro PHP čistě na vás. PHP verze se řeší na straně „runneru“, tedy té části GitLabu, která přímo spouští testy. Pokud je potřeba jenom jedna verze, tak ji stačí nainstalovat pro daného runnera. Pro více verzí je to složitější, nejjednodušší způsob je nainstalovat dalšího runnera pro druhou verzi a tu verzi mu dát k dispozici.
3.8.2.5 Podpora dalších služeb a systémů Všechny závislosti si stejně jako pro PHP musíme vyřešit sami a není tu žádný standardní postup. To znamená, že pokud chceme podporu například RabbitMQ, tak musíme ručně RabbitMQ nainstalovat. Další nevýhoda spočívá v tom, že si musíme zajistit sami, že po doběhnutí celého buildu se všechny služby vrátí na původní podoby a nezůstanou nám nějaké zprávy ve frontě třetí služby, které by rozbily následující build. Drobná výhoda spočívá v tom, že můžeme mít spojení na ostatní systémy, aniž bychom je museli kompletně replikovat v testovacím prostředí.
3.8.2.6 Úroveň reportingu Pro každý projekt si můžeme zvolit osoby, které mají dostat notifikaci, případně i ten, kdo způsobil vadný build. Notifikace je možné zasílat vždy (tedy i v případě, že build projde, což nedoporučuji) nebo jen když nějaký build selže. Notifikace je možné zasílat těmito kanály: Email Slack Bohužel GitLab momentálně nepodporuje žádné další možnosti, což je škoda, ale předpokládám, že do budoucna se další přidají.
43
GitLab nabízí grafy, jak úspěšné buildy jsme měli v minulosti.
6 Ukázka úspěšnosti buildu za poslední týden, zdroj: vlastní tvorba
7 Ukázka úspěšnosti buildu za poslední měsíc, zdroj: vlastní tvorba
8 Ukázka grafu, jež charakterizuje délku běhu posledních 30 buildu, zdroj: vlastní tvorba
44
9 Ukázka úspěšnosti celého projektu, zdroj: vlastní tvorba
3.8.2.7 Konfigurace Konfigurace se provádí výhradně skrz webové rozhraní. Pro každý repozitář / projekt můžete mít definováno několik různých úkolů a pro jaké commity se mají spouštět. Příkladem může být následující konfigurace.
10 Ukázka konfigurace pro spuštění unit testů, zdroj: vlastní tvorba
Job pro spuštění integračních testů
11 Ukázka konfigurace pro integrační testy, zdroj: vlastní tvorba
Integrační testy nechceme pouštět na jakémkoliv serveru, vzhledem k jejich náročnosti. Proto máme uvedený tag, které servery mají integrační testy spouštět. 45
Job pro akceptační testování
12 Ukázka konfigurace pro akceptační testování, zdroj: vlastní tvorba
Akceptační testování může být implementováno například pomocí knihovny Cucumber nebo může jít jen o prosté přesunutí aplikace do document rootu a její zbuildování klasickým způsobem jako na produkci. Akceptační testování je to nejnáročnější ze všech a mnohdy vyžaduje i testování uživatelem, proto jej podmiňujeme pouze spuštěním na základě GIT tagu a ne pro každý commit. Obvykle tagujeme verze, než je jdeme releasnout, viz kapitola o release managmentu.
4 Deployovací a CI managment v praxi Až doteď jsem popisoval různé přístupy a postupy, jaké jsou možné nástroje. V následujících kapitolách popíšu proces, jakým způsobem jsem postupoval při implementaci continuous integration serveru a serveru pro deployment ve firmě Eastbiz Corporation. Spoustu času jsem strávil výběrem vhodných nástrojů a experimentováním. Několikrát jsem se musel dokonce všechno vzít a smazat, protože to nebylo optimální řešení.
5 GitLab GitLab je software, který primárně hostuje GIT repozitáře. Jednotlivé git repozitáře si můžeme procházet v přehledném webovém rozhraní. 46
GitLab se velice podobá GitHubu, na rozdíl od něj však můžeme GitLab provozovat na vlastním serveru. GitLab jsem zvolil právě kvůli tomu, že jej můžeme provozovat na vlastním serveru a mít k němu přístup jenom skrz VPN připojení, což například u BitBucketu, či GitHubu není možné. Dalším důležitým aspektem byla cena, GitLab je v „community edition“ zcela zdarma.
5.1 Instalace GitLab je napsaný v Ruby on Rails a pro svůj běh vyžaduje řadu různých komponent. Dříve byl GitLab distribuovaný jako samostná Ruby on Rails aplikace a bylo na serverovém správci, aby obstaral všechny potřebné komponenty, jako je databáze, Ruby apod. Tento způsob byl nepraktický, špatně se GitLab aktualizoval a celkově to přinášelo spoustu problémů. Aktuálně je GitLab distribuovaný jako omnibus balíček, což není nic jiného než sada receptů pro knihovnu Chef (velice podobný projekt jako je již výše zmíněný Puppet). GitLab stačí nainstalovat a za pomoci konfigurace jej upravit. Do podrobnějšího popisu se nechci pouštět, protože to je mimo rozsah této práce a s CI či deploymentem to nemá nic společného. Pouze uvedu minimalistickou konfiguraci ## Gitlab # Url on which GitLab will be reachable. external_url 'https://gitlab.example.com' gitlab_rails['gitlab_email_from'] = '
[email protected]' gitlab_rails['gitlab_signup_enabled'] = false #Disallow signup
6 GitLab CI Jaký zvolit continuous integration server bylo vskutku velice těžké.
47
Travis je bohužel možné provozovat pouze ve spojení s GitHubem. Investice do GitHubu by představovala pro naši velikost přibližně $200 za měsíc. Další náklad by byl samotný Travis, který stojí pro naši velikost přibližně $250 za měsíc. Pokud bychom brali v potaz online verzi GitLabu, tak by celkově Travis a GitHub stály o $450 měsíčně více než kombinace GitLab a GitLab CI. Dalším problémem je bezpečnost, GitHub i Travis jsou veřejně dostupné služby a tudíž nemohou být schovány v privátní síti naší společnosti. Na základě těchto důvodů jsem se rozhodl právě pro GitLab hostovaný na našich serverech i za cenu toho, že musíme vynaložit jednorázovou investici do času systémového administrátora.
6.1 Instalace Pokud jste použili omnibus verzi GitLabu při instalaci, tak instalace GitLab CI je jenom o odkomentování těchto řádků v konfiguraci v /etc/gitlab/gitlab.rb #CI Server ## Url on which GitLab CI will be reachable ci_external_url 'https://ci.eastbiz.com:1337' gitlab_ci['gitlab_server'] = { "url" => 'https://gitlab.example.com', "app_id" => 'REPLACE_WITH_INFO_FROM_GITLAB', "app_secret" => 'REPLACE_WITH_INFO_FROM_GITLAB' } gitlab_ci['gitlab_ci_email_from'] = '
[email protected]'
Následně je možné se přihlásit. Přihlášení používá OAuth z klasického GitLabu.
7 Kompilace pomocí Phingu Na projektu potřebujeme spouštět řadu různých úkolů. Například: Spustit unit testování Spustit statickou analýzu kódu Udělat build pro produkci Udělat build pro vývojové prostředí Spustit integrační testy Spustit funkcionální testy
48
Samozřejmě všechny tyto úkoly je možné psát ručně přes příkazovou řádku. Problémem je, že to není automatizovaný přístup, a jak jsem zmínil v prvních kapitolách, ruční přístup je anti-pattern. Kupříkladu pro přípravu Symfony2 buildu v produkčním prostředí musíme provést tuto sadu úkonů [25]: 1. Zkontrolovat, že aplikace může běžet v tomto prostředí. 2. Konfigurace připojení do databáze, smtp serveru apod. 3. Instalace závislostí pomocí Composeru. 4. Promazání cache a vygenerování nové. 5. Zkompilovat statické soubory a přesunout je do složky dostupné z webového prohlížeče. Pak mohou ještě následovat volitelné kroky: 6. Spustit databázové migrace. 7. Vyčistit APC cache. 8. Aktualizace CRON tabulky. 9. Nahrání nových statických souborů do CDN hostingu. 10. Notifikace monitorovacího nástroje o deploymentu. Jak je vidět ze seznamu, není to nic krátkého a dělat to manuálně není to pravé. Tyto úkoly je samozřejmě možné také umístit do skriptu, pomocí kterého deployujete nebo pouštíte CI build. Problém je v tom, že testy chcete pouštět na více místech. Chcete je pouštět jak na CI serveru, tak u vývojáře v jeho vývojové instanci.
Pokud bychom
nepoužili systém, jako je Phing, tak by byl pravděpodobně celý proces navázaný na dané prostředí a nebyl by přenositelný jinam. Zároveň je výhoda Phingu v tom, že je složen z menších úkolů a ty je možné spouštět samostatně.
49
7.1 Proč Phing nemůže dělat kompletní deployment U jiných projektů například u Magephp jsem se setkal s přístupem, že je build i celý deployment zapsán dohromady v projektu a spouští se z počítače DevOp. Tento přístup se mi nelíbí z mnoha důvodů: Bezpečnost – špatně se řeší oprávnění, protože má DevOp přístup ke všem úkolům. Náchylné na chybu - DevOp má obvykle SSH přístup na vzdálený server do více projektů a špatně zvolená konfigurace může vskutku velice jednoduše přepsat jiný projekt než DevOp zamýšlel. Není možné koordinace více lidí - výpis z konzole je obvykle viditelný jenom v terminálu osoby, která deploy zahájila. V případě rozsáhlých projektů a nestabilního internetového připojení u DevOps může docházet ke komplikacím (internet přestane fungovat uprostřed deploye a musíme zajistit konzistenci na serveru). Phing nabízí sadu metod pro kopírování souborů a práci s nimi na vzdáleném úložišti, takže by bylo možné tento postup také implementovat, ale kvůli již zmíněným nedostatkům jsem jej zavrhnul.
7.2 Proč mít build konfiguraci v rámci projektu Dříve jsme drželi globální konfiguraci, tedy měli jsme obecné šablony pro Symfony2, Nette atd. sdílené mezi projekty. Tento postup se nám moc neosvědčil, protože jednotlivé úkoly a jejich komplexnost nabyly na takovém rozsahu, že přinášely více nedostatků než užitku. Dalším nevýhoda tohoto postupu spočívá v tom, že se jednotlivé projekty vyvíjejí jinou rychlostí a mají tedy závislosti na určité verze knihoven. Pokud nějaká z nich změní v nové verzi její volání, tak projekt nebude možné zbuildovat. Ve finále to totiž končilo tak, že jsme se báli aktualizovat tyto globální šablony, abychom nerozbili nějaký projekt, se kterým často nepracujeme. Mnohem lepší a jednodušší řešení je, aby se při vytváření nového projektu zkopírovaly obecné šablony pro daný typ přímo do repozitáře k projektu a neudržovala se žádná další
50
závislost. Takto máme zaručenou jistotu, že i když se k projektu vrátíme za půl roku, tak všechny úkoly budou stále fungovat.
7.3 Build od nuly oproti inkrementálnímu buildu Při deploymentu na produkční server prakticky vždy začínáme build od nuly, tedy nemáme nic předgenerováno, máme čistou aplikaci tak, jak je v repozitáři. Problémem ovšem je, když se například vývojář přepne z jedné větve v Gitu do druhé, tak je třeba nejprve „uklidit“ a pak teprve spustit potřebný build. Toto se dá navázat na automatický script, který to bude dělat za vývojáře ihned po změně.
7.4 Mít Phing nainstalovaný v systému nebo v rámci projektu Phing je možné mít nainstalovaný jako součást systému vedle PHP, Composeru a dalších služeb. Obrovská výhoda tohoto přístupu spočívá v tom, že můžeme spustit Phing kdykoliv bez jakékoliv předchozí instalace. Tento způsob se nejčastěji uplatňuje u Composeru, kdy je nainstalována jedna verze v rámci celého systému a jednotlivé projekty jej nemusí instalovat. Bohužel Phing má na rozdíl od Composeru mnohem silnější vazbu na konkrétní implementaci úkolů. Ne vždy je totiž možné zapsat potřebnou činnost pouze za pomocí build.xml, v tento moment musíme sáhnout po implementaci vlastních úkolů. Implementace se provádí přes novou PHP třídu, která dědí od tříd ve Phingu. A toto je právě kámen úrazu, vzhledem k tomu, že se musí podědit konkrétní třídy, tak vzniká silná vazba mezi Phingem a projektem. Tato silná vazba znamená, že je projekt závislý na nějaké konkrétní verzi Phingu a tudíž není dobré jej mít nainstalovaný v rámci systému, protože by mohla nastat situace, že projekt A potřebuje Phing verze 2.8, ale projekt B potřebuje Phing ve verzi 2.5. Phing je k dispozici jako balíček pro instalaci přes Composer, stačí tedy, aby byla definovaná závislost na Phingu v projektovém composer.json. Tím zajistíme, že náš build používá správnou verzi Phingu a vyvarujeme se případných problémů s kompatibilitou. Nevýhoda spočívá v tom, že musíme nejprve nainstalovat závislosti přes composer a až potom spustit samotný build. Z teoretického hlediska by měly být závislosti instalovány až v rámci build procesu, ale to bohužel není možné.
51
7.5 Konfigurace Phingu Phing je vskutku hodně komplexní nástroj, který se pravděpodobně nejvíce podobá technologii Ant z prostředí vývojového jazyka Java. Phing nemá žádné grafické rozhraní a spouští se jen za pomocí příkazové řádky. Většina konfigurace je uložena v souboru ve formátu XML. Phing hledá ve výchozím nastavení build.xml. Konfigurace se skládá z properties a targets. 7.5.1 Properties Jedná se o proměnné. Je vhodné do nich napsat veškeré konfigurační volby, cesty k složkám a souborům apod. Properties je možné zapsat i do dalších souborů, což je zejména vhodné pro konfiguraci prostředí. 7.5.2 Targets Target lze volně přeložit jako úkol, nadále budu používat české označení úkol. Úkoly definují, co přesně má Phing udělat, když je daný úkol zavolán. Ve většině případů se bude jednat o volání dalších programů. Jednotlivé úkoly jde také vázat mezi sebou, jinými slovy lze vytvořit závislost jednoho úkolu na druhém. Nejdříve doběhne druhý úkol a pak se teprve spustí ten, který definoval závislost. Ukázková konfigurace pro Symfony2 je k dispozici v příloze 11.3.2 Phing Build.
8 Webistrano Webistrano jsem zvolil jako nástroj pro deployment z několika důvodů. Je opensource a je zdarma. Velice populární, ke dni 22. 04. 2015 má na GitHubu 847 hvězdiček. Řeší bezvýpadkový deployment. Umožňuje více fází pro projekt (vývojová a produkční). Umí deployment na více serverů. Řeší autentizaci a autorizaci. 52
Samotné Webistrano má pouze podporu pro Ruby on Rails a nikoliv podporu pro PHP projekty. Proto jsem začlenil do projektu ještě knihovnu Capifony, jež rozšiřuje podporu o možnost nasazovat projekty postavené na frameworku Symfony2. Dalším rozšířením je knihovna pro nasazení projektů postavených na Frameworku Nette. Bohužel žádnou knihovnu jsem nenašel, a proto jsem si ji napsal sám. Pracovně jsem ji pojmenoval jako Nettify. Pro novější projekty používající Phing jsem ještě doplnil podporu pro typ projektu Phing. Zároveň jsem také připravil knihovnu pro deployment projektů nad redakčním systémem Wordpress. Upravená verze je k dispozici v příloze 11.1 Webistrano.
8.1 Konfigurace na serveru Doporučuji si vytvořit pro Webistrano nového uživatele a umístit zdrojové soubory Webistrana do jeho domovského adresáře. Hlavní konfigurace se nachází v souboru config/webistrano_config.rb. Tento soubor při instalaci zatím neexistuje a je potřeba, abyste jej vytvořili. Jeho ukázku, jak by měl vypadat, naleznete v souboru config/webistrano_config.rb.sample. Konfigurace pro připojení do databáze se nachází v souboru config/database.yml. Opět tento soubor v distribuci neexistuje a je třeba jej vytvořit. Jeho ukázku naleznete v souboru config/database.yml.sample. Konfigurace je hotova a nyní je možné Webistrano spustit. Je několik možností a pro testovací, či vývojové prostředí doporučuji jej spustit pomocí Webrick1. Provedete to tímto příkazem ruby script/server -d -p 3000 -e production
1
Webrick je knihovna pro Ruby on Rails, která poskytuje jednoduché webové služby (sama o sobě funguje
jako webový server).
53
Následně se inicializuje webový server na portu 3000 a Webistrano bude k dispozici na adrese http://host:3000 Výchozí přihlašovací jméno je admin a heslo admin. Po prvním spuštění důrazně doporučuji toto heslo změnit, popřípadě vytvořit nového uživatele a uživatele admin deaktivovat. Pro produkční nasazení aplikace je možné použít tato řešení [26]: WEBrick – pomalé, vhodné na testování Mongrel – rychlé a stabilní, ovšem složitější instalace Apache2/Nginx + mod_passenger – jednoduchá instalace Unicorn – rychlé a robustní Díky jednoduché
konfiguraci
popíšu,
jak
na
produkci
nastavit
Apache2
s mod_passengerem pro práci s Webistranem. Vzhledem k zaměření této práce na deployment a nikoliv na konfiguraci linuxové serveru budu předpokládat, že máte již nainstalovaný a funkční Apache2 s virtualhosty. Nejprve doinstalujeme podporu pro mod_passenger, to uděláme sérií příkazů: apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7 apt-get install libapache2-mod-passenger gem install passenger passenger-install-apache2-module
Nyní bychom se měli dostat na obrazovku, která se nás ptá, jak chceme Passenger nainstalovat do Apache.
54
13 Dialogové okno při instalaci Phusion Passenger, zdroj: vlastní tvorba
Stačí, pokud vyberete možnost č. 1. Pokud vše proběhlo bez problému, můžeme vytvořit nový virtualhost, jehož definice bude vypadat takto:
ServerName deploy.domain.com DocumentRoot /home/webistrano/www/public RailsEnv production RailsBaseURI /webistrano PassengerPoolIdleTime 7200
Doplňte si prosím správnou doménu a správnou cestu k adresáři Webistrana. Poté stačí jen restartovat Apache a vše by mělo fungovat. V případě,
že
narazíte
na
chybu
„`add_frozen_gem_path':
undefined
method
`source_index' for Gem:Module (NoMethodError)“, tak musíte přeinstalovat gem systém na verzi 1.8.25. Provedete to následujícím příkazem: gem update --system 1.8.25
55
8.2 Konfigurace aplikačního serveru 8.2.1 Zabezpečení privátního klíče Budeme pracovat s tezí, že nechceme pro každý projekt vytvářet nový deployment klíč a kopírovat jej na každý produkční server, kde chcete mít aplikaci nasazenou. Pokud bychom to takto nespecifikovali, tak bychom měli spoustu práce s vytvořením nového projektu. S tímto přichází i riziko, pokud unikne tento privátní klíč, tak potenciální útočník má univerzální klíč ke všem aplikacím. Řešením by bylo použít nástroj pro konfigurační managment typu Chef nebo Puppet a do scriptu pro zakládání nového projektu přidat zavolání odpovídající operace na založení nového uživatele a vygenerování klíče. Budeme mít jeden privátní klíč, který bude mít přístup do GIT repozitáře projektů, které se mají deployovat. Tento klíč uložíme na stejný server, kde běží Webistrano. Využijeme vlastnost SSH a to konkrétně ForwardAgent, která nám umožní tunelovat připojení. Vytvoříme si tedy privátní klíč, který uložíme do domovského adresáře uživatele Webistrano. Ve výchozím nastavení by se jednalo o umístění: /home/webistrano/.ssh/id_rsa
56
8.2.1.1 Spuštění SSH-Agenta Po každém přihlášení bude potřeba spustit službu SSH-AGENT [27], proto si v domovském adresáři uživatele Webistrano vytvoříme soubor start_agent.sh s obsahem: #!/bin/bash SSH_ENV="$HOME/.ssh/environment" function start_agent { echo "Initialising new SSH agent..." /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}" chmod 600 "${SSH_ENV}" source "${SSH_ENV}" > /dev/null /usr/bin/ssh-add; } # Source SSH settings, if applicable if [ -f "${SSH_ENV}" ]; then . "${SSH_ENV}" > /dev/null ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || { start_agent; } else start_agent; fi
Můžeme si vyzkoušet, že spuštění agenta funguje touto sérií příkazů: source start_agent echo "$SSH_AUTH_SOCK"
Pokud agent je spuštěný, tak by nám druhý příkaz měl vrátit umístění linuxového socketu, například: webistrano@devel:~$ echo "$SSH_AUTH_SOCK" /tmp/ssh-lyochnsWG917/agent.917
8.2.1.2 Automatické spouštění agenta Nyní jen stačí zajistit, že se script bude spouštět po každém přihlášení uživatele Webistrano. Pokud neexistuje následující soubor, tak jej vytvoříme, jinak jej stačí upravit. /home/webistrano/.bashrc
Na konec souboru vložíme příkaz, který zajistí, že po přihlášení uživatele se spustí agent. 57
source ~/start_agent
Poslední věcí je, že povolíme, jaké servery mohou využívat ssh agenta. Vytvoříme si soubor: /home/webistrano/.ssh/config
A do něj vložíme všechny aplikační servery, kterým chceme povolit tunelování. Příkladem může být například toto: Host web1.example.com ForwardAgent yes Host web2.example.com ForwardAgent yes Host web3.example.com ForwardAgent yes Host web4.example.com ForwardAgent yes
Je možné uvést i wildcard, tedy * na místo názvu hostu. Toto důrazně nedoporučuji, mohlo by to být bezpečnostní riziko, protože by bylo všem umožněno tunelovat připojení.
8.2.1.3 Test, zdali tunelování funguje Pokud si to budeme chtít vyzkoušet, tak se přihlásíme z uživatele Webistrano na aplikační server pomocí příkazu: webistrano@devel:~$ ssh
[email protected]
A následně se můžeme pomocí tohoto příkazu dostat na server s repositáři. Důležitý je parametr –T, který povolí tunelované připojení. project@app-server:~$ ssh
[email protected] -T
8.2.2 Automatické skripty pro založení nové stránky Připravil jsem automatické skripty, které je možné použít pro založení nového projektu na aplikačním serveru. Skripty jsou k dispozici v příloze 11.2 Server scripts. 58
Skripty stáhněte či příkazem GIT clone uložte do složky /root/server-scripts. V první řadě je třeba upravit výchozí šablony tak, aby vyhovovaly vašim potřebám. Apache virtualhost má šablonu uloženou v souboru: /root/server-scripts/create-vhost/apache-vhost.default.conf
Šablonu upravte do podoby, aby vyhovovala konfiguraci vašeho webového serveru (umístění document rootu, logy aj.). Dalším důležitou věcí, co musíte upravit, je soubor s veřejným klíčem, který používá Webistrano. /root/server-scripts/create-vhost/authorized_keys.default
Do tohoto souboru vložte veřejný klíč, který jste vygenerovali na začátku kapitoly 5.3.1 Posledním krokem je vložení otisku SSH certifikátu ze serveru, který obsahuje GIT repozitáře. Tento otisk vložte do souboru: /root/server-scripts/create-vhost/known_hosts.default
Vše by již mělo být nakonfigurováno a můžete spustit skript /root/server-scripts/create-vhost/create-vhost.sh
Skript se vás zeptá na dvě jednoduché otázky. Jaká bude doména pro projekt, tedy například client.example.com a jaký bude název projektu. Tento název projektu bude použit i jako uživatel, tedy je vhodné zvolit něco bez mezer, háčků, čárek a mělo by to být jednoznačné a krátké. Například client-app.
8.2.3 Zajištění bezvýpadkového deploymentu [28] Webistrano pro zajištění atomicity používá symlink, který vede ze složky current do konkrétní verze. Problém je v tom, že PHP používá 2 minutovou cache pro funkci realpath a pokud změníme symlink, tak PHP stále bude používat starou verzi aplikace. Bohužel součásti nové verze, kterou jsme právě nasadili, mohla být i databázová migrace a stará verze aplikace nemusí být s novou verzí databáze kompatibilní. Také je problém, pokud 59
máme více aplikačních serverů, tak každý z nich může používat rozdílné verze, což může způsobovat nepříjemné problémy, které se špatně odhalují. Jedním z možných řešení by bylo tuto cache vypnout, ale to by mohlo způsobit výkonnostní problémy. Mnohem lepším řešením, je upravit konfiguraci virtualhostu ve webovém serveru, aby posílal reálnou cestu do PHP interpreteru a nikoliv cestu, která obsahuje symlink.
8.2.3.1 Nginx Ve webovém serveru Nginx lze použít proměnnou $realpath_root. Toto je standartní konfigurace tak, jak je uváděna v klasickém manuálu, používá cestu přes symlink a tudíž je použita cache. fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
Pokud chceme použít reálnou cestu, tak řádek upravíme do následující podoby: fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
8.2.3.2 Apache2 Apache2 bohužel momentálně nemá žádné nativní řešení a je třeba jej řešit dodatečným modulem. Jeden z modulů je mod_realdoc. [29] Prakticky jej stačí jen nainstalovat, povolit a Apache začne používat reálné cesty.
8.3 Vytvoření projektu a dostupná konfigurace Nyní bychom měli mít vše připraveno pro běh Webistrana. Proto přejdeme na webové rozhraní a přihlásíme se.
60
14 Grafické rozhraní Webistrana, zdroj: vlastní tvorba
Na levé straně máme přehled vytvořených projektů, seznam aplikačních serverů (Hosts), vlastních receptů a seznam uživatelů. Uprostřed stránky vidíme poslední provedené nasazení aplikace a jejich výsledek.
8.3.1 Vytvoření nového projektu Kliknutím na tlačítko „Current projects“ přejdeme na seznam aktuálních projektů a dole vidíme tlačítko New project. 61
15 Založení nového projektu, zdroj: vlastní tvorba
Měli bychom zvolit jednoznačné jméno projektu bez diakritiky a mezer. Zároveň by mělo být stejné jako název projektu, který jsme uvedli v kroku 8.2.2 Automatické skripty pro založení nové stránky. Pokud bychom tak neučinili, tak by vygenerovaná konfigurace projektu byla nekonzistentní s nastavením serveru a museli bychom ji ručně upravit. Zvolíme doménu v absolutní podobě bez www, tedy například example.com. Pak už zbývá jen zvolit typ projektu. Každý projekt má specifickou konfiguraci a adresářovou strukturu. Tato možnost nejde později změnit.
62
Podporované a vyzkoušené projekty Název projektu
Popis
Symfony2
Symfony2 Framework připravený pro poslední LTS verzi 2.4.0. Funguje pro databázové připojení Doctrine 2
Nette
Nette Framework, připravený pro verzi 2.1
Wordpress
Známý redakční systém, hlavní rozdíl oproti čistému PHP projektu je v předpřipravené konfiguraci složek wp_content a wp_upload
PHP
Čistý PHP projekt, neobsahuje žádné složité skripty
Phing
Webistrano samo o sobě rozumí projektům a umí je správně deployovat. Pokud ale chceme provádět sofistikovanější operace na více různých prostředích, je mnohem lepší přesunout veškeré buildovací záležitosti do Phingu a na Webistranu nechat jen doručení konkrétní aplikace na server a případný rollback.
Nyní bychom měli mít úspěšně založený projekt a k dispozici detail projektu.
63
16 Detail projektu typu Symfony2, zdroj: vlastní tvorba
64
8.3.2 Stages Každý projekt může mít několik fází. Obvykle máme dvě verze aplikace, jednu aktuálnější, která je pravidelně nasazována na testovací prostředí. A druhou verzi, která je označena jako produkční a je dostupná klientům. Seznam fází je k dispozici na detailu projektu v části „Stages“.
17 Ukázka záložky fází projektu, zdroj: vlastní tvorba
Po rozkliknutí se dostaneme na konkrétní fázi.
18 Detail konkrétní fáze projektu, zdroj: vlastní tvorba
65
Můžeme upravit konfigurační volby, například nastavit environment na development apod. Konfiguračním volbám se budu věnovat v další kapitole. Used recipes nám umožnují speciálně pro tento projekt definovat další úkoly. Například synchronizace s externím systémem aj. Více informací o tomto tématu je k dispozici v kapitole „Rozšíření specifická pro projekt“. Pro deployment je klíčově důležitá sekce „Deployed hosts“, tato sekce obsahuje veškeré servery, kam se bude aplikace nasazovat.
19 Na jaký server nasadit aplikaci, zdroj: vlastní tvorba
Role obsahuje tři možnosti: App – pro naše účely bychom měli vždy zvolit tuto možnost Db – pro případ, že daný projekt má ovládat db Web – pro případ, že se jedná pouze o statický web
66
Dále jsou k dispozici další zaškrtávátka: Primary – použitelné pro roli DB No release – z repositáře se nenačtou na produkční server žádné zdrojové soubory. Použitelné zejména pro DB. No symlink – neaktualizuje se symlink na aktuální verzi a tudíž nebude aplikace okamžitě nasazena. V záložce host vybereme, na jaký server chceme tuto aplikaci v této fázi nasadit.
8.4 Konfigurační volby Možnosti konfigurace jsou rozsáhlé vzhledem k tomu, že Webistrano potažmo Capistrano lze používat na spousty způsobů. Uvedu pouze pro nás nejdůležitější konfigurační volby. 8.4.1 Základní konfigurace Konfigurační
Defaultní konfigurace
Popis
application
-
Unikátní název aplikace
deploy_to
/home/www/project/domain
Do jakého adresáře na vzdáleném
parametr
serveru budeme deployovat deploy_via
:checkout
Je několik způsobů, jak nahrát zdrojové
soubory
na
vzdálený
server. Pro naše potřeby postačí checkout.
Další
možnosti
jsou
popsané v dokumentaci [28] newrelic_appname
-
Pokud chceme notifikovat externí službu NewRelic při každém novém nasazení aplikace.
rails_env
production
Konfigurace
běhového
režimu,
zejména pro Rails aplikace repository
[email protected]:project.git Repozitář se zdrojovými soubory dané aplikace 67
scm
:git
O jaký verzovací systém se jedná, buďto GIT nebo SVN
shared_children
[]
Sdílené
složky
napříč
všemi
soubory
napříč
všemi
verzemi. shared_files
[]
Sdílené verzemi.
ssh_keys
/home/webistrano/.ssh/id_rsa Umístění
privátního
klíče
na
lokálním serveru user
project
Pod jakým uživatelem se bude Webistrano přihlašovat na vzdálený server
use_sudo
false
Je třeba pro všechny příkazy na vzdáleném serveru pouštět přes sudo
web_path
www
Adresář,
kam
směřuje
webový
server copy_vendors
true
V
případě
použití
Composeru.
Pokud se nezmění závislost ani její verze,
tak
zkopírovat
závislosti
z předchozího releasu use_composer
true
Používat
Composer
pro
načtení
závislostí branch
master
Z jaké větve gitu stáhnout zdrojové soubory
68
8.4.2 Symfony2 konfigurace Konfigurační
Defaultní
parametr
konfigurace
app_config_file
parameters.yml Soubor s konfiguračními parametry, který je
Popis
specifický pro každý server app_path
app
Složka app v Symfony2 podání
assets_symlinks
true
Používat symlinky pro assets
dump_assetic_assets
true
Zdali se mají generovat assets (statické soubory) v průběhu deploye
permission_method
acl
Jaký je namespace pro příkazy s oprávněním Složka s dočasnými cache soubory
remote_tmp_dir symfony_env_local
dev
Jak se nazývá v konfiguraci vývojové prostředí
symfony_env_prod
prod
Jak se nazývá v konfiguraci produkční prostředí
8.5 Deployment Deployment je složen z řady jednotlivých úkolů, těmto úkolům se také říká recepty. Každý úkol (task) má nějaký svůj recept a má definované podmínky, kdy je spuštěn (jaký úkol tomu například předchází atd.). Ten nejsložitější úkol je právě deploy, který pouští velké množství dalších menších úkolů. Výhodou tohoto rozdělení na úkoly je to, že můžeme jednotlivé úkoly spouštět samostatně a ručně. Na produkčním serveru se při prvním nasazení aplikace vytvoří tři složky. current releases shared Každá verze aplikace má vlastní složku v releases. A aktuální verze (current) je pouhým symlinkem do releases. To znamená, že pokaždé, když se pustí deploy, tak se vytvoří nová složka v releases s aktuálním datem a časem. V ní se provedou veškeré dílčí úkoly, a pokud vše proběhne bez chyby, tak se změní symlink u current na tuto složku v releases. Složku current má webový server nakonfigurovanou jako document root. 69
Bohužel toto má nevýhodu, pokud chceme klientům umožnit nahrávat si soubory skrz webové rozhraní. Pokud by to fungovalo jenom takto, tak při každé nové verzi by všichni klienti přišli o svá nahraná data. Proto existuje ještě třetí složka shared. Ta obsahuje sdílené soubory a složky napříč všemi verzemi. Tedy pokud máme nějaké úložiště pro klientská data, tak jej označíme v parametru shared_files (pro konkrétní soubory) nebo shared_children (pro složky). Doporučuji do těchto sdílených složek dávat co nejméně dat. Změna struktury dat uvnitř sdíleného prostoru, je neskutečně složitá vzhledem k faktu, že souborový systém neumožňuje transakční zpracování. To ve výsledku znamená, že pokud připravíme script na změnu struktury a nastane v něm chyba, která zamezí správnému dokončení, tak není ani žádná možnost, jak se vrátit do původního stavu. Další nevýhoda spočívá v tom, že i když se celý deployment provede v pořádku, tak přijdeme o možnost provést rollback. Neexistuje totiž cesta, jak se jednoduše dostat na původní strukturu. V případě, že se deployment nepovede, například v průběhu nastane nějaká chyba, tak se deployment nedokončí a spustí rollback.
70
20 Ukázka deploymentu, zdroj: vlastní tvorba
8.6 Oprávnění a přístupová práva Uživatel se přihlašuje pomocí svého přihlašovacího jména, které slouží i pro jeho identifikaci v systému. Například ve výpisu posledních deploymentů vidíme právě toto
71
uživatelské jméno. V Detailu uživatele si můžeme ještě zobrazit email a v jaké časové zóně se mu mají zobrazovat časy deploymentů. Uživatel může být označen jako administrátor. Poté má přístup do všech projektů a může s nimi bez omezení manipulovat. Toto je vhodné pro systémového administrátora, který připravuje nové projekty. Pokud uživatel není admin, tak se mu musí přiřadit oprávnění k danému projektu a k dané fázi. Dalším označením je disabled. Pokud uživatele takto označíme, tak se nemůže přihlásit do systému. Tato funkce nahrazuje smazání uživatele, protože pokud bychom ho opravdu smazali, tak bychom přišli o informace o tom, jaký deployment kdy provedl. Jak již bylo zmíněno výše, uživatel má práva na úrovni projektů, tak na úrovni konkrétních fází. Přidáme tedy uživateli oprávnění na našem testovacím projektu. Tím sice uvidí daný projekt, ale nedostane se do konkrétních fázi projektu. Přejdeme tedy do fáze projektu. Můžeme mu přiřadit klasické oprávnění, které mu umožní spouštět deployment a další příkazy. Nebo mu můžeme oprávnění označit jako read only. To znamená, že uvidí veškeré deploymenty a příkazy, které byly spuštěné, ale nebude mít oprávnění je spustit.
8.7 Další dostupné příkazy 8.7.1 Rollback Prakticky nejdůležitějším příkazem je rollback. Pokud se stane, že omylem nasadíme špatnou verzi aplikace, která je defektní, tak ji potřebujeme co nejrychleji z té produkce také stáhnout. Z tohoto důvodu zavoláme příkaz rollback, který na vzdálených serverech změní symlink pro current na předchozí verzi. 8.7.2 Databázové migrace Dalším důležitým příkazem je práce s databázovými migracemi. Databázové migrace by mohly být součástí akce deploy. Ale z bezpečnostních důvodů jsem je tam nedal. Mohlo by se totiž stát, že nasadíme špatnou verzi, provede se migrace. My zjistíme, že verze není funkční, tak dáme rollback a to provede migrace směrem dolu, při kterých dojde ke ztrátě dat. 72
Z tohoto důvodu jsou migrace jako samostatný příkaz. Pro databázové migrace máme sadu příkazů doctrine:migrations. 8.7.3 Promazání cache Pro promazání cache máme k dispozici příkazy cache:clear a cache:warmup. Clear cache promaže a warmup ji zase připraví pro produkční nasazení aplikace.
8.8 Rozšíření specifická pro projekt Některé projekty mohou vyžadovat po nasazení speciální úkoly. Například chceme stáhnout z externího systému aktuální ceník a synchronizovat zaměstnance. Mohli bychom vytvořit tento recept pro celý projekt, ale ostatní projekty by tento druh úkolu měly definován zbytečně (končil by chybou). Proto můžeme napsat recept speciálně pro projekt. V levém menu vybereme Recipes (recepty) a vytvořím nový. Recepty jsou automaticky verzovány. Ukázkový recept jak po nahrání projektu na server, lze spustit například build pomocí phingu. before "deploy:create_symlink", "phing:build" namespace :phing do task :build, :except => { :no_release => true } do run "cd #{current_release} && bin/phing" end end
8.9 Napojení na NewRelic NewRelic je monitorovací služba, která sleduje dostupnost a výkon aplikací. Jedna z mnoha funkcí, které nabízí, je porovnání stavu aplikace před deploymentem a po něm. Aby toto bylo možné, tak je třeba NewRelic nějakým způsobem notifikovat. Proto je zabudovaná podpora pro tuto službu právě ve Webistranu.
73
8.9.1 Konfigurace V aplikaci Webistrano vytvoříme soubor: app/newrelic.yml
Překopírujte do něj obsah ze šablony, jež je v souboru: app/newrelic.yml.sample
Následně je třeba ještě doplnit váš NewRelic licence key. Tento klíč naleznete pod záložkou Account settings v informačním systému NewRelicu. Ještě je potřeba přiřadit projekt k aplikaci na NewRelicu. Tato konfigurační volba je již přidána do výchozí konfigurace. newrelic_appname
client.example.com
Odteď se při každém deploymentu aplikace pošle upozornění, že byla nahrána nová verze na aplikační server. Ovšem problém bývá, jak identifikovat aplikaci pro newrelic pro sbírání dat. Pokud ta aplikace implementuje bundle pro newrelic [29], tak není problém. Ovšem co když se jedná o projekt na wordpressu nebo Nette? I toto umí deployment zařídit, automaticky se po každém nasazení nové verze aplikace přidá tento script do .htaccess.
php_value newrelic.appname "client.example.com"
Není tedy nutné upravovat každou aplikaci, kterou chceme hlídat.
74
8.9.2 Ukázka Pokud vše půjde podle plánu, tak bychom v průběhu deploymentu měli vidět následující log. executing `newrelic:notice_deployment' triggering before callbacks for `newrelic:notice_deployment' executing "echo -e \"
\ php_value newrelic.appname \"shipito.com\" \ \" >> /home/www/example/example.com/releases/20140324063835/www/.htaccess" servers: ["app1.example.com"] [app1.eastbiz.com] executing command command finished in 20ms
To nám zajistí, že všechny dotazy jdoucí na naši aplikaci budou i na straně NewRelicu přiřazeny ke správné aplikaci. Na konci úspěšného deploymentu by měla být vidět hláška o úspěšné notifikaci NewRelicu. * Uploading deployment to New Relic ** Uploaded deployment information to New Relic * executing `deploy:restart`
75
Teď se již můžeme podívat do služby NewRelic. Mezi events (události) uvidíme informaci o nové verzi aplikace.
21 Upozornění na nový deployment v NewRelicu, zdroj: vlastní tvorba
22 Seznam proběhlých deploymentů a jejich statistiky, zdroj: vlastní tvorba
Pro každou verzi máme statistiky chybovosti, průměrné doby odezvy na straně serveru i na straně klienta (javascript, zbuildování HTML aj). AppDex score je procentuální vyjádření spokojenosti zákazníků na základě rychlosti odpovědi.
76
K dispozici je také detail konkrétního deploymentu. První, co uvidíme, je sumarizace hodnot
A pak grafy.
23 Doba odezvy a počet požadavků na server, zdroj: vlastní tvorba
Na tomto grafu je vidět, jak vývojář v nové verzi aplikace zavedl statické cachování, čímž snížil počet dotazů na aplikaci (data jsou poskytována rovnou Apachem a aplikace se to ani nedotkne). Čímž se na chvíli zvýšila odezva, protože se ta cache musela nejdříve vygenerovat. Po chvíli už je většina dat poskytována z cache, čímž se snížila doba odezvy. Všechny ostatní grafy se snížily prakticky okamžitě, převážně ale kvůli další optimalizaci skriptů.
24 Vytížení CPU při staré a nové verzi aplikace, zdroj: vlastní tvorba
77
25 Využití paměti při staré a nové verzi aplikace, zdroj: vlastní tvorba
26 Graf spokojenosti návštěvníků, zdroj: vlastní tvorba
Vzhledem k charakteru aplikace, jež musí při každém požadavku kontaktovat desítky různých externích API, není možné uspokojit návštěvníka rychlou odezvou. Zde by bylo lepší posunout hranice očekávané odezvy na vyšší úroveň.
8.10 Definice vlastních šablon a úkolů Vzhledem k tomu, že Webistrano je pouze jen nástavba nad Capistranem, tak pořád můžeme psát klasické recepty pro Capistrano. Umístění je ve složce lib/webistrano/template
78
Každý typ projektu by zde měl mít svůj vlastní soubor. S tím, že implementace konkrétních úkolů lze oddělit do dalších složek, jako to například dělá Capifony nebo Nettify. Šablona Base.rb slouží k obecným úkolům napříč všemi programovacími jazyky. BasePHP.rb je primárně PHP šablona obsahující výchozí konfiguraci pro PHP. Pokud budeme chtít napsat své vlastní rozšíření, tak si vytvoříme nový soubor: lib/webistrano/template/example_project.rb
V něm si definujeme submodul struktury Webistrano / Template / ExampleProject. Webistrano pro běh vyžaduje dvě proměnné CONFIG a TASKS. Proměnná config obsahuje HashMap. Zde je příklad: CONFIG = { :application => "%PROJECT NAME%", :deploy_to => "/home/www/%PROJECT NAME%/%DOMAIN NAME%/", :deploy_via => ":checkout", :repository => "
[email protected]:%PROJECT NAME%.git", :scm => ":git", :ssh_keys => "/home/webistrano/.ssh/id_rsa", :user => "%PROJECT NAME%", :use_sudo => "false", :branch => "master", :newrelic_appname => "%DOMAIN NAME%", :web_path => "www" }.freeze
Jak je vidět z ukázky, můžeme použít zástupné znaky %PROJECT_NAME% a %DOMAIN%. V oficiální dokumentaci tuto funkci nenajdete, protože se jedná o mé vlastní rozšíření.
79
Obvykle ale nebudeme chtít začít konfiguraci vždy od znova a je vhodné využít předpřipravené šablony. Vzhledem k tomu, že HashMap CONFIG je zmražené a nedá se s ním už nijak operovat, tak je třeba jej naklonovat a spojit s novým polem. Ukázka může být například následující konfigurace: CONFIG = Webistrano::Template::BasePHP::CONFIG.dup.merge({ :remote_tmp_dir => 'temp', :app_path => "app", :web_path => "www", :app_config_file => "app/config/local.neon", :use_composer => true, :shared_children => "[\"temp\",\"log\"]", :shared_files => "[\"app/config/local.neon\"]", :nette_console => "www/index.php" }).freeze
CONFIG je relevantní pouze při vytváření projektu. Tedy jakmile je projekt již vytvořen, jakákoliv změna v proměnné CONFIG nebude brána v potaz. Je možné změnit konfiguraci ručně přes webové rozhraní nebo pro hromadnou změnu na více projektech doporučuji napsat jednoduchý skript, který doplní potřebnou hodnotu do databáze. Konkrétně budete potřebovat přidat hodnoty do tabulky configuration_parameters. TASKS slouží k definici úkolů, co je možné spouštět. Dokonce je možné určit, jaký úkol se spustí po jakém. Využívá se zde výhod skriptovacího jazyku, jako je Ruby. Díky tomu, že jazyk Ruby není kompilovaný, tak je možné psát zdrojový kód do proměnné a spustit jej později. Přesně tohoto využívá právě Capistrano. Tedy do proměnné TASKS se zapisují ruby skripty, které jsou později spouštěny při jejich zavolání.
80
Příklad takového skriptu. task = "" example_libs = ["nette"] #These files will be loaded example_libs.each{ |fileName| task = task + IO.read("lib/webistrano/template/nette/" + fileName + ".rb"); } own_task = <<-'EOS' after "deploy:finalize_update" do if use_composer if update_vendors nette.composer.update #Run method from example_libs else nette.composer.install end end end
Jak je vidět z ukázky, tak se po úkolu finalizate_update spustí náš příklad a zavolá buďto composer.update, nebo composer.install. Proto je třeba tyto úkoly definovat. Vytvoříme si tedy soubor: lib/webistrano/template/nette/nette.rb
81
V něm bude třeba definovat úkol pro composer.update. Následující ukázku můžete vložit do vytvořeného souboru. task = "" namespace :nette do namespace :composer do desc "Runs Composer to update vendors, and composer.lock file" task :update, :roles => :app, :except => { :no_release => true } do if composer_bin nette.composer.self_update else nette.composer.get set :composer_bin, "#{php_bin} composer.phar" end logger.info "--> Updating Composer dependencies" run "#{try_sudo} bash --login -c 'cd #{latest_release} && #{composer_bin} update #{composer_options}'" logger.info "ok" end end
Z ukázky je názorně vidět, že každý úkol je začleněn do namespace, v našem případě se jedná o nette.composer. Dále má každý úkol svůj popis, který je použitý v GUI, nastavíte ho zavoláním funkce desc a jako parametr přebírá právě popis. Pokud potřebujete zobrazit nějakou informaci o průběhu procesu, je možné použít výstup do dialogového okna v prohlížeči zavoláním logger.info a jako parametr uvedete právě onu zprávu.
82
8.11 Nedostatky Asi největším nedostatkem Webistrana je jeho neaktuálnost. Poslední oficiální změna je z 20. května 2011 a od té doby existuje spousta dalších verzí, ale žádná z nich není přidána do originální verze, tudíž je vskutku těžké dát dohromady funkční verzi. Díky tomu, že neexistují aktualizace, tak ani není Webistrano použitelné s nejnovější verzí ruby a je nutné jej provozovat na staré verzi. Dalším problémem je, že kompilace projektu a instalace závislostí se provádí až na cílovém serveru. Toto je nevýhoda v tom, že všechny nástroje potřebné pro „kompilaci“ je třeba mít nainstalované na daném serveru (například se jedná o NPM, Grunt, Gulp, Bower, Compass, Google Closure aj.). Pokud chceme provést deployment na 5 serverů, tak na pěti serverech musíme mít všechny nástroje nainstalované. Webistrano sice umožňuje, aby se provedla kompilace na jeho straně a na cílový server se pak kopírovala už hotová aplikace, toto řešení ale bylo problémové kvůli používání absolutních cest při kompilaci a různých verzí pro různé nástroje. Pokud jedna aplikace potřebuje PHP ve verzi 5.3 a druhá ve verzi 5.5, tak na Webistrano serveru musí být nainstalovány obě dvě a u spousty nástrojů je složité je mít nainstalovány vedle sebe v různých verzích. Další nevýhodou tohoto postupu bylo to, že při kompilaci nebylo možné zkontrolovat, jestli má aplikace na aplikačním serveru všechny potřebné technologie pro běh (například chybějící rozšíření do PHP).
9 Závěr Povedlo se najít optimální řešení, pro automatizovaný deployment a continuous integration, které vyhovuje kritériím zvoleným v úvodní kapitole. Řešení je navrženo tak, že jednotlivé části jsou oddělené a vždy vykonávají jednu konkrétní činnost. 1. Gitlab – hostuje GIT repozitáře. 2. Gitlab CI – continuous integration server, který zajišťuje všechny potřebné kroky pro úspěšné kolečko continuous integration. 3. Phing – kompiluje, připravuje projekty a provádí úkoly pro dané cílové prostředí. 4. Webistrano – přesouvá projekt na správný server a zajišťuje deploy / rollback. 5. NewRelic – zajišťuje notifikace o deploymentu a hlídá chyby. Výhoda navrženého řešení je zejména v jeho konfigurovatelnosti, jakmile přestane jedna komponenta splňovat požadavky, tak se dá velice jednoduše nahradit jinou technologií. 83
Popsané řešení bylo úspěšně realizováno ve společnosti Shipito LLC. Firma byla ve špatné technologické situaci, produkovala aplikace, které vykazovaly velké množství chyb, neměla standardizovaný postup, jak vyvíjet aplikace. Případů, kdy produkční aplikace přestala fungovat kvůli špatnému deploymentu nebo nedostatečnému testování, byla spousta, bohužel nebyly ani zdokumentovány. Bylo rozhodnuto o změně a začaly se hledat nástroje a postupy. Současně s tím, jak se zkoušely různé nástroje a postupy, tak vznikala tato bakalářská práce.
9.1 Původní stav Firma Shipito LLC neměla žádný continuous integration systém, z toho vyplynula i frustrace vývojářů k psaní testů, protože je zapomínali spouštět, následně se staly neaktuální a nebyly dlouhodobě udržovány. Deployment probíhal buďto pomocí FTP nebo Rsync protokolu, ale vše se dělalo ručně. Existovala pouze dokumentace, jak projekt rozběhnout. Bohužel zde byl opět problém lidského syndromu a dokumentace nebyla aktualizována. Postupem času se tedy stala těžce neaktuální a deployment jakéhokoliv projektu trval dlouho, bylo velké riziko lidské chyby1 a zároveň se znalost, jak provést správně deployment, špatně sdílela s novými lidmi. Vzhledem k tomu, že vše probíhalo ručně, tak není ani dochována informace, kolik chyb nastalo a kolikrát se deployment nepovedl a skončilo to nedostupností aplikace.
9.2 Po implementaci continuous integration a automatizovaného deploymentu Continuous integration systém provedl více než 10,000 cyklů. Úspěšnost provedení je přibližně 84%. Z čehož vyplývá, že přibližně 1600 různých verzí bylo defektních a kompetentní osoba byla náležitě informována. Automatizovaný deployment aktuálně řeší 23 projektů a dohromady byly aplikace více než 2060x deploynuty. Neúspěšných pokusů o deployment je aktuálně 427. Tímto způsobem jsme zabránili deploynutí defektní aplikace ve 427 případech. 1
Mnohdy se stalo, že aplikace nebyla v produkčním nasazení dostupná, protože vývojář
zapomněl nahrát nějaký soubor, či se prostě spletl v postupu. 84
Bohužel není možné změřit, jak se zlepšila kvalita a snížila chybovost aplikací vzhledem k tomu, že nejsou k dispozici historická data před implementací celého procesu. Alespoň přikládám subjektivní vyjádření provozního ředitele: „After our development team implemented continuous integration system and automated deployment system, our applications had great improvement. We did not experience any significant service disturbances any more, which benefits both our customers and our services. Another advantage of implementing continuous integration system and automated deployment system, we reduce the time to release new features to the minimum as well. I consider this project a key success that helps us to not only anchor the 2nd largest company in our industry; but also to move forward to surpass our competitors.“ Jason Luong, COO
9.3 Budoucí rozšíření Do budoucna bych zvážil nahrazení Webistrana za jinou technologii, pokud se nadále nebude vyvíjet, vzhledem ke stále složitějšímu zajištění kompatibility kvůli závislosti na nepodporované verzi Ruby. Vzhledem k tomu, jak je koncipovaná práce, tak by nahrazení jedné části nemělo být složité. Do budoucna bude také zajímavé sledovat, jak se vyvine nastupují trend v podobě aplikačních kontejnerů, například pomocí technologie Docker nebo Vagrant.
10 Conclusion We have successfully found an optimal solution for automated deployment and continuous integration, which suits the needs specified in the first chapter. Solution is designed to be completely independent in used technology or tools. Each part is responsible only for doing single smallest piece. 1. Gitlab – GIT repositories are hosted there. 2. Gitlab CI – continuous integration server is responsible for running complete CI cycle.
85
3. Phing – Phing is responsible for compiling and preparing projects for specified environment. It contains various targets, which can fulfill various different tasks. 4. Webistrano – Webistrano is responsible for moving project on final server and is capable of doing deploy and rollback. 5. NewRelic – Newrelic is the monitoring system and is responsible for sending notification about deployment to DevOps team. Huge advantage of this solution is in configurability. If we are not satisfied with one technology, we can very easily replace it with a different one. Solution, which has been invented in this Bachelor’s thesis, has been successfully implemented in company Shipito LLC. The company used to be in a very bad technological situation. Applications were delivered with an enormous amount of issues and bugs. There wasn’t any standardized process for proper development. There were a lot of cases when application in production stopped working because of a mistake made during the deployment. Applications were also completely without any tests. Unfortunately there is no proper documentation to show how many issues occurred before implementing solution described in this thesis. Due to the mentioned reasons, company decided to improve this situation and that’s why I started to look for various tools, procedures etc. During the realization I’ve started to write this bachelor’s thesis.
10.1 Original situation Company Shipito LLC was completely without system for continuous integration, because of this, developers always forgot to run tests and it led to a situation where tests were outdated. Deployment process used to be done manually by FTP protocol or Rsync. There used to be documentation for how to compile application. Unfortunately there was always someone who forgot to update documentation when he changed something and it led to outdated documentation. Deployment was complicated; it took a lot of time and effort to deploy any
86
application. There was a huge problem with human factor, and also knowledge to properly deploy application couldn’t be shared. Given that deployment was done manually, there is no information on how many issues and problems company had with this process.
10.2 After company implemented continuous integration process and automated deployment Continuous integration system ran more than 10,000 cycles. About 84% were successful. So about 1,600 different versions contained some issue and responsible person for this was informed. Automated deployment actually has 23 projects and together all applications were deployed more than 2,060x. Unsuccessful tries for deployment are 427, which means system didn’t allow defected version to be deployed to production 427 times. Unfortunately there is no way to measure how this process helped with quality of application and how it lowered number of issues with applications, due to the fact that we don’t have any historic data before implementing this process. I’m enclosing evaluation of this project by COO at company Shipito LLC: „After our development team implemented continuous integration system and automated deployment system, our applications had great improvement. We did not experience any significant service disturbances any more, which benefits both our customers and our services. Another advantage of implementing continuous integration system and automated deployment system, we reduce the time to release new features to the minimum as well. I consider this project a key success that helps us to not only anchor the 2nd largest company in our industry; but also to move forward to surpass our competitors.“ Jason Luong, COO at Shipito
87
10.3 Future extension I would consider replacing Webistrano with different technology, due to the fact that Webistrano is no longer maintained and it’s becoming very difficult to run it, because of it’s dependency on an unsupported version of Ruby. Luckily, how I designed this process, all parts are replaceable and to exchange Webistrano with different technology would be pretty easy. I would also consider following the principle of application containers, which are becoming more and more popular. Famous implementations are Docker or Vagrant.
88
11 Příloha A – Přiložené CD 11.1 Webistrano Oficiální webistrano je zastaralé. Přiložená verze mého Webistrana je rozšířena o podporu Nette, Wordpressu. Umí rozlišit uživatelská oprávnění dle projektu a umí pracovat s doménou, tudíž je možné velice zrychlit zakládání projektu. Dále má integraci s NewRelicem. Konkrétní změny a vylepšení jsou k vidění v přiloženém GITu. Nejnovější verze je vždy na adrese https://github.com/JakubKohout/webistrano
11.2 Server scripts Vlastnoručně napsané skripty, které urychlují vytvoření nového uživatele a virtual hostu na aplikačním serveru. Je k dispozici varianta pro Apache2 i Nginx. Nejnovější verze je vždy na adrese https://github.com/JakubKohout/server-scripts.
11.3 Symfony2 Demo Jedná se o základní verzi Symfony2 ukázky, kde demonstruji technologie popsané a použité v rámci této práce. Všechny mé změny jsou k dispozici k vidění jako commity v přiloženém GITu. Nejnovější verze je vždy na adrese https://github.com/JakubKohout/symfony-demo. 11.3.1 Fixtures Fixtures jsou k nalezení ve složce /src/AppBundle/Tests/Fixtures. Je ukázáno několik přístupů jak s použitím klasického Fakeru, tak s použitím Populatoru, kterému stačí jen název entity a je schopen ji vygenerovat (zkusí uhádnout data). 11.3.2 Phing Build Pro Phing je připravený build soubor /build.xml. Jednotlivé úkoly se dají spouštět přes /bin/phing. Připravil jsem několik základních úkolů build, build-dev, build-ci. Připravil jsem i rozšíření, které zajistí to, že pro každé prostředí existuje vlastní konfigurace. Ukázková konfigurace je v souboru /build/properties.local.
89
11.3.3 Testy Jsou připraveny integrační testy a unit testy ve složce /src/AppBundle/Tests/. Testy obsažené ve výchozí ukázce Symfony2 byli natolik dobré, že jsem je ani neupravoval. Nejsem tudíž jejich autorem. 11.3.4 Doctrine Migrations Základní ukázka migrací v doctrine je k dispozici ve složce /app/DoctrineMigrations.
90
12 Seznam obrázků 1 Jednotlivé kroky CI, Vlastní tvorba .................................................................................. 12 2 Deployment pipeline, autor: Continuous integration ........................................................ 17 3 Schéma nasazení aplikace pomocí GIT hooku, zdroj: vlastní tvorba ............................... 32 4 Schéma nasazení aplikace pomocí Capistrana, zdroj: vlastní tvorba ............................... 34 5 Topologie GitLab CI, zdroj: oficiální stránka GitLab CI https://about.gitlab.com/gitlabci/ ......................................................................................................................................... 42 6 Ukázka úspěšnosti buildu za poslední týden, zdroj: vlastní tvorba .................................. 44 7 Ukázka úspěšnosti buildu za poslední měsíc, zdroj: vlastní tvorba .................................. 44 8 Ukázka grafu, jež charakterizuje délku běhu posledních 30 buildu, zdroj: vlastní tvorba44 9 Ukázka úspěšnosti celého projektu, zdroj: vlastní tvorba................................................. 45 10 Ukázka konfigurace pro spuštění unit testů, zdroj: vlastní tvorba .................................. 45 11 Ukázka konfigurace pro integrační testy, zdroj: vlastní tvorba ...................................... 45 12 Ukázka konfigurace pro akceptační testování, zdroj: vlastní tvorba .............................. 46 13 Dialogové okno při instalaci Phusion Passenger, zdroj: vlastní tvorba .......................... 55 14 Grafické rozhraní Webistrana, zdroj: vlastní tvorba ....................................................... 61 15 Založení nového projektu, zdroj: vlastní tvorba ............................................................. 62 16 Detail projektu typu Symfony2, zdroj: vlastní tvorba .................................................... 64 17 Ukázka záložky fází projektu, zdroj: vlastní tvorba ....................................................... 65 18 Detail konkrétní fáze projektu, zdroj: vlastní tvorba ...................................................... 65 19 Na jaký server nasadit aplikaci, zdroj: vlastní tvorba ..................................................... 66 20 Ukázka deploymentu, zdroj: vlastní tvorba .................................................................... 71 21 Upozornění na nový deployment v NewRelicu, zdroj: vlastní tvorba............................ 76 22 Seznam proběhlých deploymentů a jejich statistiky, zdroj: vlastní tvorba ..................... 76 23 Doba odezvy a počet požadavků na server, zdroj: vlastní tvorba ................................... 77 24 Vytížení CPU při staré a nové verzi aplikace, zdroj: vlastní tvorba ............................... 77 25 Využití paměti při staré a nové verzi aplikace, zdroj: vlastní tvorba.............................. 78 26 Graf spokojenosti návštěvníků, zdroj: vlastní tvorba ..................................................... 78
91
13 Seznam zdrojů 1. SENSIOLAB. Symfony2 documentation. DoctrineFixturesBundle [online]. 2015 [cit. 2015-03-15]. Dostupné z: http://symfony.com/doc/current/bundles/ DoctrineFixturesBundle/index.html 2. ZANINOTTO, F. Fzaninotto Faker. Github [online]. 2015 [cit. 2015-03-01]. Dostupné z: https://github.com/fzaninotto/Faker 3. PADRAIC. Github. padraic / mockery [online]. 2015 [cit. 2015-02-20]. Dostupné z: https://github.com/padraic/mockery 4. BERGMANN, S. PHPUnit official webpage. Testing framework for PHP [online]. 2015 [cit. 2015-03-28]. Dostupné z: https://phpunit.de/ 5. FOUNDATION, N. Nette Tester official webpage. Nette Tester – enjoyable unit testing [online]. 2015 [cit. 2015-03-20]. Dostupné z: http://tester.nette.org/en/ 6. phpFashion. Proč používám nette tester [online]. Dostupné také z: http:// phpfashion.com/proc-pouzivam-nette-tester 7. Pagerduty official webpage. Stop Incidents From Becoming Emergencies. [online]. Dostupné také z: http://www.pagerduty.com/ 8. Flash Player Help. Archived Flash Player versions [online]. Dostupné také z: https:// helpx.adobe.com/flash-player/kb/archived-flash-player-versions.html 9. Semantic Versioning 2.0.0 [online]. Dostupné také z: http://semver.org/ 10. HUMBLE, J. a D. FARLEY. Continuous delivery. In: Reliable software releases through build, test, and deployment automation.. Addison-Wesley Professional, 2010, s. 39-41. ISBN 9780321601919. 11. RFC 765. FILE TRANSFER PROTOCOL (FTP) [online]. 1985 [cit. 2014-01-31]. Dostupné z: https://tools.ietf.org/html/rfc959 12. FTP Security Considerations. RFC 2577 [online]. 1999 [cit. 2014-01-31]. Dostupné z:
92
https://tools.ietf.org/html/rfc2577 13. Zdrojak.cz. „Prostě to tam nahrajte FTPčkem“ – nebo ne? [online]. 2011 [cit. 201401-31]. Dostupné z: http://www.zdrojak.cz/clanky/proste-to-tam-nahrajte-ftpckemnebo-ne/ 14. rsync web pages. rsync manual page [online]. 2014 [cit. 2014-01-31]. Dostupné z: https://rsync.samba.org/ftp/rsync/rsync.html 15. Phinx oficiální stránka. Phinx: PHP Database Migrations for everyone [online]. 2015 [cit. 2015-04-02]. Dostupné z: https://phinx.org/ 16. Zdrojak.cz. Deploy aplikace přes git [online]. 2013 [cit. 2015-01-31]. Dostupné z: http://www.zdrojak.cz/clanky/deploy-aplikace-pres-git/ 17. GitHub. Travis CI: Free continuous integration platform for GitHub projects [online]. 2013 [cit. 2015-04-06]. 18. Github - Travis. Adding BitBucket support [online]. 2012 [cit. 2015-04-06]. Dostupné z: https://github.com/travis-ci/travis-ci/issues/667 19. Travis CI. Security Statement: System Security [online]. 2013 [cit. 2015-04-06]. Dostupné z: https://billing.travis-ci.com/pages/security 20. Databases and other services. Services (data stores, messaging brokers, etc) in the Travis CI Environment [online]. 2015 [cit. 2015-04-06]. Dostupné z: http://docs.travisci.com/user/database-setup/ 21. Travis CI. Configuring Build Notification [online]. 2015 [cit. 2015-04-06]. Dostupné z: http://docs.travis-ci.com/user/notifications/ 22. Coveralls. Test Coverage History & Statistics [online]. 2015 [cit. 2015-04-20]. Dostupné z: https://coveralls.io/ 23. Nette Framework. Continuous integration with Nette Tester [online]. 2015 [cit. 201504-06]. Dostupné z: http://doc.nette.org/en/2.3/testing-with-travis#toc-result
93
24. Configuring your build. Build Lifecycle [online]. 2013 [cit. 2015-04-06]. Dostupné z: http://docs.travis-ci.com/user/build-configuration/#Build-Lifecycle 25. Symfony The Coockbook. How to Deploy a Symfony Application: Common PostDeployment Tasks [online]. 2014 [cit. 2015-04-10]. Dostupné z: http://symfony.com/ doc/current/cookbook/deployment/tools.html#common-post-deployment-tasks 26. GitHub. FAQ Frequently Asked Questions [online]. 2011 [cit. 2014-04-16]. Dostupné z: https://github.com/peritor/webistrano/wiki/FAQ---Frequently-Asked-Questions 27. Mark's personal page. Using ssh-agent with ssh [online]. 2013 [cit. 2014-04-21]. Dostupné z: http://mah.everybody.org/docs/ssh 28. Blog Forrest79. Deploy PHP aplikací, bez výpadku a pod (velkou) zátěží [online]. 2014 [cit. 2015-04-15]. Dostupné z: http://blog.forrest79.net/?p=493 29. Code as Craft. Atomic deploys at Etsy [online]. 2013 [cit. 2015-02-10]. Dostupné z: https://codeascraft.com/2013/07/01/atomic-deploys-at-etsy/ 30. Webistrano documentation. Configuration Parameters [online]. 2012 [cit. 2014-0421]. Dostupné z: https://github.com/peritor/webistrano/wiki/Configuration-Parameters 31. GitHub. Ekino NewRelic Bundle [online]. 2015 [cit. 2015-04-20]. Dostupné z: https:// github.com/ekino/EkinoNewRelicBundle 32. Getting Git Right. 10 years of Git [online]. 2015 [cit. 2015-04-20]. Dostupné z: https:// www.atlassian.com/git/articles/10-years-of-git/ 33. Developer Survey 2015. Source control [online]. 2015 [cit. 2015-04-20]. Dostupné z: http://stackoverflow.com/research/developer-survey-2015#tech-sourcecontrol
94