phing i fabric - budowanie i deployment aplikacji webowych

Post on 16-Apr-2017

256 Views

Category:

Software

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

PHING I FABRICBudowanie i deployment aplikacji webowych

Leszek KrupińskiPHPers #1, 20 maja 2013 r.

Leszek Krupiński@leafnode http://leafnode.pl/

2001: FAQ pl.comp.lang.php

2001: Tłumaczenie podręcznika

We’re hir

ing!

Kilka konferencji, kilka wykładów, jedno szkolenie, kilka artykułów, jeden wywiad.

OBECNIEBezpieczeństwo, scalability, architektura

DO RZECZYDużo slajdów, nie zwracajcie na nie większej uwagi

CO BUDOWAĆ?Generowanie plików statycznych, dynamicznych, minimalizacja,

konfiguracja, parametryzacja, spełnianie wymogów (uprawnienia)...

PO CO AUTOMAT?

BRAK PORZĄDKU WPROWADZA ZMIANY

http://www.flickr.com/photos/jasonpoon/3926723912/© Jason Poon, CC-BY-NC-SA

POWTARZALNOŚĆZa każdym razem brak błędu lub te same błędy

http://www.flickr.com/photos/legofenris/4641828205/© leg0fenris, CC-BY-NC-SA

WIARYGODNE PRZYGOTOWYWANIE

PAKIETÓW WYJŚCIOWYCHhttp://www.flickr.com/photos/snowblink/2228929261/

© Jon Lim, CC-BY-NC-ND

REJESTRACJA BAZY WIEDZYhttp://www.flickr.com/photos/jezpage/4047231133/

© Jeremy Page, CC-BY-NC-ND

PHINGPHing Is Not GNU make

Wzorowany na Apache Ant

CECHY

• Łatwy do rozszerzania

• Składnia XML

• Gotowe taski integrujące z popularnymi pakietami

• Wywoływanie kodu PHP

INSTALACJAPoprzez PEAR:

pear channel-discover pear.phing.infopear install phing/phing

$ phing -v Phing 2.5.0

INSTALACJAPoprzez Composer:

{ "require": { "phing/phing": "2.5.0" }}

$ ./vendor/bin/phing -v Phing 2.5.0

PROSTY PLIK BUILDUZazwyczaj nazywany build.xml

<?xml version="1.0" encoding="UTF-8"?><project name="FooBar" default="dist"> <target name="prepare"> <echo msg="Making directory ./build" /> <mkdir dir="./build" /> </target> <target name="build" depends="prepare"> <echo msg="Copying files to build directory..." /> <echo msg="Copying ./about.php to ./build directory..." /> <copy file="./about.php" tofile="./build/about.php" /> <echo msg="Copying ./browsers.php to ./build directory..." /> <copy file="./browsers.php" tofile="./build/browsers.php" /> <echo msg="Copying ./contact.php to ./build directory..." /> <copy file="./contact.php" tofile="./build/contact.php" /> </target> <target name="dist" depends="build"> <echo msg="Creating archive..." /> <tar destfile="./build/build.tar.gz" compression="gzip"> <fileset dir="./build"> <include name="*" /> </fileset> </tar> <echo msg="Files copied and compressed in build directory OK!" /> </target> </project>

COŚ PROSTSZEGO

<?xml version="1.0" encoding="UTF-8"?> <project name="HelloWorld" default="hello"> <target name="hello" description="Wyświetla powitanie"> <echo msg="Hello, world!" /> </target> </project>

Buildfile: /home/leafnode/phing/1/build.xmlHelloWorld > hello: [echo] Hello, world!BUILD FINISHEDTotal time: 0.0630 seconds

SKŁADOWE PLIKU

• Project

• Target

• Task

• Property

PROJECTGłówny węzeł pliku, zawiera jeden lub więcej celów (targets)

TARGETGrupa zadań wykonywanych jako całość

ZADANIEElement którego wykonanie ma wykonać pewną funkcję

PROPERTYZmienna

<?xml version="1.0" encoding="UTF-8"?> <project name="HelloWorld" default="hello"> <target name="hello" description="Wyświetla powitanie"> <property name="imie" value="Jasio" /> <echo msg="Cześć, ${imie}!" /> </target> </project>

WBUDOWANE PROPERTIESos.name, php.version, user.home itp.

http://www.phing.info/docs/guide/stable/chapters/appendixes/AppendixA-FactSheet.html#BuiltInProperties

ZEWNĘTRZNE PROPERTIESŁatwa konfiguracja buildu

LINIA POLECEŃphing -Dimie=”Zbyszek”

ZEWNĘTRZNY PLIK<property file="./build.properties" />

# Pary klucz/wartość#klucz=wartość# This dir must contain the local applicationbuild.dir=../# Credentials for the database migrationsdb.host=localhostdb.user=userdb.pass=passworddb.name=example# paths to programsprogs.mysql=/usr/bin/mysql

Buildfile: /home/leafnode/phing/3/build.xmlHelloWorld > hello: [property] Loading /home/leafnode/phing/3/./build.properties [echo] Cześć, Jasio!BUILD FINISHEDTotal time: 0.0657 seconds

WIELE TARGETÓW

<?xml version="1.0" encoding="UTF-8"?> <project name="HelloWorld" default="hello"> <target name="hello" description="Wyświetla powitanie"> <property file="./build.properties" /> <echo msg="Cześć, ${imie}!" /> </target> <target name="bye"> <echo msg="Papa!" /> </target> </project>

DOMYŚLNIE WEDŁUG ATRYBUTU

Wskazanie konkretnego targetu:$ phing nazwa_targetu

BLOKOWANIE URUCHAMIANIA RĘCZNEGO

“-” przed nazwą targetu

ZALEŻNOŚCI

<?xml version="1.0" encoding="UTF-8"?> <project name="HelloWorld" default="bye"> <target name="hello" description="Wyświetla powitanie"> <property file="./build.properties" /> <echo msg="Cześć, ${imie}!" /> </target> <target name="bye" depends=”hello”> <echo msg="Papa!" /> </target> </project>

Buildfile: /home/leafnode/phing/5/build.xmlHelloWorld > hello: [property] Loading /home/leafnode/phing/5/./build.properties [echo] Cześć, Jasio!HelloWorld > bye: [echo] papaBUILD FINISHEDTotal time: 0.0797 seconds

WIELE ZALEŻNOŚCIdepends="pre-init, build, package"

RĘCZNE WYWOŁYWANIE TARGETÓW

Np. narzędziowych

<target name="process"> <echo msg="Processing ${data}" /></target> <target name="build"> <phingcall target="process"> <property name="data" value="some data" /> </phingcall> </target>

ZEWNĘTRZNY PLIK

<phing phingfile="utils.xml" target="bazingify"> <property name="bazinga" value="meh" /></phing>

IMPORTOWANIE CAŁEGO PLIKU

<import file="build.utils.xml" />

PRACA NA ZBIORACH PLIKÓW

<target name="copyfiles"> <copy todir="/tmp/deploy"> <fileset dir="." includes="**/*.php" /> </copy> </target>

ZŁOŻONE WARUNKI

<fileset dir="." includes="**/*.php"> <and> <size value="1024" when="more" /> <date datetime="20-05-2013 18:00" when="after" /> </and> </fileset>

FILTRY

<target name="copyfiles"> <property file="./build.properties" /> <copy todir="/tmp/deploy"> <filterchain> <replacetokens begintoken="@@" endtoken="@@"> <token key="DBNAME" value="${db.name}" /> <token key="DBUSER" value="${db.user}" /> <token key="DBPASS" value="${db.pass}" /> </replacetokens> </filterchain> <fileset dir="." includes="**/*.php" /> </copy> </target>

ZMIANA NAZW PLIKÓW

<mapper type="glob" from="*.bat" to="*.txt"/>

<mapper type="regexp" from="^(.*)\.ent\.xml$" to="\1.php"/>

INSTRUKCJE WARUNKOWE

<if> <equals arg1="${foo}" arg2="bar" /> <then> <echo message="The value of property foo is bar" /> </then> <else> <echo message="The value of property foo is not bar" /> </else> </if>

<condition property="isMacOrWindows"> <or> <os family="mac"/> <os family="windows"/> </or> </condition>

PĘTLE

<foreach param="filename" absparam="filename" target="print"> <fileset dir="."> <include name="*.php" /> </fileset> </foreach>

INTERAKCJA<input propertyname="env" defaultValue="dev">Jakie środowisko?</input>

WYWOŁYWANIE FUNKCJI PHP

<php function="strtoupper" returnProperty="builddir"> <param value="${tag}" /></php>

PRZEGLĄD TASKÓW

<-- List the contents of "/home". --><exec command="ls -l" dir="/home" /> <-- Start the make process in "/usr/src/php-4.0". --><exec command="make" dir="/usr/src/php-4.0" /> <-- List the contents of "/tmp" out to a file. --><exec command="ls -l /tmp > foo.out" escape="false" />

<-- Exit with message --><fail message="Failed for some reason!" /><-- Exit if ${errorprop} is defined --><fail if="errorprop" message="Detected error!" /> <-- Exit unless ${dontfail} prop is defined. --><fail unless="dontfail" message="Detected error!" />

<mail tolist="user@example.org" subject="build complete">The build process is a success...</mail>

<chmod file="/home/test/mine.txt" mode="0500" verbose="true" />

<svncopy username="user" password="pass" repositoryurl="svn://localhost/phing/trunk/" todir="svn://localhost/phing/tags/1.0"/> <svnexport repositoryurl="svn://localhost/project/trunk/" todir="/home/michiel/dev"/> <svnlastrevision repositoryurl="svn://localhost/project/trunk/" propertyname="lastrev"/><echo>Last revision: ${lastrev}</echo>

<gitinit repository="${repo.dir.resolved}" /> <gitclone repository="git://github.com/path/to/repo/repo.git" targetPath="${repo.dir.resolved}" /> <gitpull repository="${repo.dir.resolved}" all="true" />

<docblox title="API Documentation" destdir="apidocs" template="new_black"> <fileset dir="./classes"> <include name="**/*.php" /> </fileset> </docblox>

<jsMin targetDir="docroot/script/minified" failOnError="false"> <fileset dir="docroot/script"> <include name="**/*.js"/> </fileset> </jsMin>

<phpunit codecoverage="true"> <formatter type="xml" todir="reports" /> <batchtest> <fileset dir="src"> <include name="**/*Test.php" /> </fileset> </batchtest> </phpunit>

<zip destfile="output.zip"> <fileset dir="build"> <include name="**/*.php" /> </fileset> </zip>

DEPLOYMENTFabric

CZEMU NIE DEPLOYMENT PRZEZ PHING?

Można, ale XML.

ZDALNE POLECENIE

<?xml version="1.0"?><project name="sshtest" default="main"> <target name="main"> <ssh username="username" password="password" host="192.168.1.200" command="pwd" /> </target> </project>

<ssh username="username" password="password" host="192.168.1.200" command="pwd" property="mypwd" display="false" /><echo>The present working directory is ${mypwd}</echo>

KOPIOWANIE PLIKÓW

<scp username="john" password="smith" host="webserver" todir="/www/htdocs/project/"> <fileset dir="test"> <include name="*.html" /> </fileset> </scp>

MIGRACJA BAZY DANYCH

<dbdeploy url="sqlite:${project.basedir}/data/db.sqlite" userid="dbdeploy" password="dbdeploy" dir="${project.basedir}/data/dbdeploy/deltas" />

http://dbdeploy.com/documentation/getting-started/rules-for-using-dbdeploy/

<pdosqlexec src="deploy.sql" url="sqlite:test.db"/>

http://www.liquibase.org/

<liquibase-update jar="/usr/local/lib/liquibase/liquibase.jar" classpathref="/usr/local/lib/liquibase/lib/mysql-connector-java-5.1.15-bin.jar" changelogFile="./changelogTest.xml" username="liquibase" password="liquibase" url="jdbc:mysql://localhost/mydatabase" />

CZEMU NIE CHEF LUB PUPPET?

DUŻO POTRAFIĄ

Kimberly VardemanCC-BY-SA

UŻYWANIE JEST SKOMPLIKOWANE

Frank Bruns-BallhausenCC-BY-SA 3.0/de

WYMAGANE DODATKOWE ZASOBY

http://www.flickr.com/photos/rolohauck/3432135840/© Roland Hauck, CC-BY-NC-SA 2.0

(i wolę Pythona od Ruby’ego ;) )

INSTALACJA

pip install fabric

INSTALACJA PIPeasy-install pip

INSTALACJA EASY-INSTALLapt-get install python-setuptools

WINDOWS

• Ze strony python.org:

• instalator python

• instalator setup-tools

• easy_install pip

• pip install fabric

PLIK WEJŚCIOWYZwykły kod Pythona

fabfile.py

from fabric.api import rundef host_type(): run('uname -s')

$ fab -H localhost,linuxbox host_type[localhost] run: uname -s[localhost] out: Darwin[linuxbox] run: uname -s[linuxbox] out: LinuxDone.Disconnecting from localhost... done.Disconnecting from linuxbox... done.

ARGUMENTY

def hello(name="world"): print("Hello %s!" % name)

$ fab hello:name=JeffHello Jeff!Done.

Polecenie lokalne: local

from fabric.api import localdef test(): local("phing unittest") def commit(): local("git add -p && git commit") def push(): local("git push") def prepare_deploy(): test() commit() push()

Polecenie zdalne: run

def deploy(): deploy_dir = '/var/www/app' with cd(code_dir): run("git pull") run("phing")

DZIAŁANIA INTERAKTYWNE

def deploy(): deploy_dir = '/var/www/app' with settings(warn_only=True): if run("test -d %s" % code_dir).failed: run("git clone user@host:repo.git %s" % code_dir) with cd(code_dir): run("git pull") run("phing")

TASKIfrom fabric.api import task, run@taskdef mytask(): run("a command")

REAKCJE[my_server] run: test -d /srv/django/myprojectWarning: run() encountered an error (return code 1) while executing 'test -d /var/www/app'[my_server] run: git clone user@pass:repo.git /var/www/app[my_server] out: Cloning into /srv/django/myproject...[my_server] out: Password: <enter password>[my_server] out: remote: Counting objects: 6698, done.[my_server] out: remote: Compressing objects: 100% (2237/2237), done.[my_server] out: remote: Total 6698 (delta 4633), reused 6414 (delta 4412)[my_server] out: Receiving objects: 100% (6698/6698), 1.28 MiB, done.[my_server] out: Resolving deltas: 100% (4633/4633), done.[my_server] out:[my_server] run: git pull[my_server] out: Already up-to-date.

PRZYKŁAD

from fabric.api import * from datetime import datetimeenv.hosts = ['appserver']

def get_ts(): d = datetime.now() return d.strftime("%Y-%m-%d_%H-%M") def deploy(): ts = get_ts() with cd("/var/www"): run("mkdir app-"+ts) put(".", "/var/www/app-"+ts) build("/var/www/app-"+ts) with cd("/var/www"): run("rm app") run("ln -s app-"+ts+" app")

PYTANIA?

LINKIhttp://www.phing.info/

http://fabfile.org/

DZIĘKUJĘ :)

http://speakerdeck.com/leafnode/

top related