Phing for power users - frOSCon8

106
Phing for power users Stephan Hochdörfer, bitExpert AG

Transcript of Phing for power users - frOSCon8

Page 1: Phing for power users - frOSCon8

Phing for power usersStephan Hochdörfer, bitExpert AG

Page 2: Phing for power users - frOSCon8

Phing for power users

About me

Stephan Hochdörfer

Head of IT at bitExpert AG, Germany

enjoying PHP since 1999

[email protected]

@shochdoerfer

Page 3: Phing for power users - frOSCon8

Phing for power users

I used to be an Ant fanboy...

Page 4: Phing for power users - frOSCon8

What is Phing?

Phing for power users

Page 5: Phing for power users - frOSCon8

What is Phing?

Phing for power users

It is a PHP project build system orbuild tool based on Apache Ant.

Page 6: Phing for power users - frOSCon8

What is Phing?

Phing for power users

Domain Specific Language for an project build system.

Page 7: Phing for power users - frOSCon8

Phing for power users

A build system for PHP code? Srsly?

Page 8: Phing for power users - frOSCon8

Glue for all 3rd party tools

Phing for power users

Page 9: Phing for power users - frOSCon8

How to install Phing?

Phing for power users

Page 10: Phing for power users - frOSCon8

$> pear channel­discover pear.phing.info$> pear install phing/phing

How to install Phing? The PEAR way...

Phing for power users

Installing Phing

Page 11: Phing for power users - frOSCon8

$> phing ­vPhing 2.5.0

$> pear channel­discover pear.phing.info$> pear install phing/phing

How to install Phing? The PEAR way...

Phing for power users

Installing Phing

Running Phing:

Page 12: Phing for power users - frOSCon8

How to install Phing?

Phing for power users

Installing Phing globally? WTF?!?

Page 13: Phing for power users - frOSCon8

How to install Phing?

Phing for power users

Phing is „just another“ dependency for your project.

Page 14: Phing for power users - frOSCon8

How to install Phing? The Composer way...

Phing for power users

Page 15: Phing for power users - frOSCon8

{"require": {

"phing/phing": "2.5.0"}

}

How to install Phing? The Composer way...

Phing for power users

composer.json:

Page 16: Phing for power users - frOSCon8

{"require": {

"phing/phing": "2.5.0"}

}

$> php composer.phar installLoading composer repositories with package informationInstalling dependencies  ­ Installing phing/phing (2.5.0)    Downloading: 100%         

Writing lock fileGenerating autoload files

How to install Phing? The Composer way...

Phing for power users

composer.json:

Running Composer:

Page 17: Phing for power users - frOSCon8

How to install Phing? The Composer way...

Phing for power users

/tmp/myproject   |­vendor   |­­­bin   |­­­­­@phing   |­­­composer   |­­­phing   |­­­­­phing   |­­­­­­­bin   |­­­­­­­­­phing   |­­­­­­­build   |­­­­­­­classes   |­­­­­­­docs   |­­­­­­­etc   |­­­­­­­test

Page 18: Phing for power users - frOSCon8

How to install Phing? The Composer way...

Phing for power users

/tmp/myproject   |­vendor   |­­­bin   |­­­­­@phing   |­­­composer   |­­­phing   |­­­­­phing   |­­­­­­­bin   |­­­­­­­­­phing   |­­­­­­­build   |­­­­­­­classes   |­­­­­­­docs   |­­­­­­­etc   |­­­­­­­test

$> ./vendor/bin/phing ­vPhing 2.5.0

Running Phing:

Page 19: Phing for power users - frOSCon8

Phing Basics

Phing for power users

Page 20: Phing for power users - frOSCon8

Phing Basics

Phing for power users

Project, Target, Task, Properties

Page 21: Phing for power users - frOSCon8

Phing Basics: Project

Phing for power users

Root node of a build file containing one or more targets.

Page 22: Phing for power users - frOSCon8

Phing Basics: Target

Phing for power users

A group of tasks that run as an entity.

Page 23: Phing for power users - frOSCon8

Phing Basics: Task

Phing for power users

Custom piece of code to perform a specific function.

Page 24: Phing for power users - frOSCon8

Phing Basics: Properties

Phing for power users

Properties (variables) help to customize execution.

Page 25: Phing for power users - frOSCon8

Phing Basics: Built-In Properties

Phing for power users

e.g. host.os, line.separator, phing.version, php.version, …

Page 26: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="init">

<target name="init">

<!­­ insert logic here ­­></target>

</project>

Phing Basics: Sample Build File

Phing for power users

Page 27: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="hello">

<target name="hello" description="Says Hello, world!">

 <echo msg="Hello, world!" /></target>

</project>

Build File – Hello World example

Phing for power users

Page 28: Phing for power users - frOSCon8

Why Phing?

Phing for power users

Runs everywhere where PHP runs.

Page 29: Phing for power users - frOSCon8

Why Phing?

Phing for power users

No additional depencendies needed(e.g. Java, …).

Page 30: Phing for power users - frOSCon8

Why Phing?

Phing for power users

More than 120 predefinedtasks to choose from.

Page 31: Phing for power users - frOSCon8

Why Phing?

Phing for power users

Easy to extend by writing custom tasks in PHP.

Page 32: Phing for power users - frOSCon8

Enforce Internal Targets

Phing for power users

Page 33: Phing for power users - frOSCon8

Enforce Internal Targets

Phing for power users

<?xml version="1.0"?><project name="myproject" default="hello">

<target name="init" description="Property initialization">

<property name="Hello" value="Hello, world!" /></target>

<target name="hello" depends="init">

<echo msg="${Hello}" /></target>

</project>

Page 34: Phing for power users - frOSCon8

Enforce Internal Targets

Phing for power users

$> ./vendor/bin/phing -f build.xml hello/tmp/myproject/build.xml

myproject > init:

myproject > hello:

[echo] Hello, world!

BUILD FINISHED

Total time: 0.0474 seconds

Page 35: Phing for power users - frOSCon8

Enforce Internal Targets

Phing for power users

$> ./vendor/bin/phing -f build.xml init/tmp/myproject/build.xml

myproject > init:

BUILD FINISHED

Total time: 0.0476 seconds

Page 36: Phing for power users - frOSCon8

Enforce Internal Targets

Phing for power users

$> ./vendor/bin/phing -lBuildfile: /tmp/myproject/build.xmlDefault target:--------------------------------------------------------- hello

Main targets:--------------------------------------------------------- init Property initialization

Subtargets:--------------------------------------------------------- hello

Page 37: Phing for power users - frOSCon8

Enforce Internal Targets

Phing for power users

Internal targets are just helpers like private methods.

Page 38: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="hello">

<target name="-init" description="Property initialization">

<property name="Hello" value="Hello, world!" /></target>

<target name="hello" depends="-init">

<echo msg="${Hello}" /></target>

</project>

Enforce Internal Targets – The solution

Phing for power users

Page 39: Phing for power users - frOSCon8

Enforce Internal Targets – The solution

Phing for power users

$> ./vendor/bin/phing -f build.xml -initUnknown argument: -initphing [options] [target [target2 [target3] ...]]Options: -h -help print this message -l -list list available targets -v -version print the version information -q -quiet be extra quiet -verbose be extra verbose -debug print debugging information

Report bugs to <[email protected]>

Page 40: Phing for power users - frOSCon8

Enforce Internal Targets – The solution

Phing for power users

Are the targets really hidden?

Page 41: Phing for power users - frOSCon8

Enforce Internal Targets

Phing for power users

$> ./vendor/bin/phing -lBuildfile: /tmp/myproject/build.xmlDefault target:--------------------------------------------------------- hello

Main targets:--------------------------------------------------------- -init Property initialization

Subtargets:--------------------------------------------------------- hello

Page 42: Phing for power users - frOSCon8

Enforce Internal Targets

Phing for power users

$> ./vendor/bin/phing -lBuildfile: /tmp/myproject/build.xmlDefault target:--------------------------------------------------------- hello

Main targets:--------------------------------------------------------- -init Property initialization

Subtargets:--------------------------------------------------------- hello

Page 43: Phing for power users - frOSCon8

Enforce Internal Targets (Improved Version)

Phing for power users

<?xml version="1.0"?><project name="myproject" default="hello">

<target name="-init"hidden="true"description="Property initialization">

<property name="Hello" value="Hello, world!" /></target>

<target name="hello" depends="-init">

<echo msg="${Hello}" /></target>

</project>

Page 44: Phing for power users - frOSCon8

$> ./vendor/bin/phing -lBuildfile: /tmp/myproject/build.xmlDefault target:--------------------------------------------------------- hello

Subtargets:--------------------------------------------------------- hello

Enforce Internal Targets (Improved Version)

Phing for power users

Page 45: Phing for power users - frOSCon8

Custom Tasks

Phing for power users

Page 46: Phing for power users - frOSCon8

Custom Tasks

Phing for power users

Phing can do way morethan simple exec calls!

Page 47: Phing for power users - frOSCon8

Custom Task (Adhoc definition)

Phing for power users

<?xml version="1.0"?><project name="myproject" default="hello">

<target name="init"> <adhoc-task name="mytask"><![CDATA[class MyTask extends Task {

/** * (non-PHPdoc) * @see \Task::main() */public function main() {

// Custom code here...}

}]]></adhoc-task>

</target>

<target name="hello" depends="init">

<mytask /></target>

</project>

Page 48: Phing for power users - frOSCon8

<?phprequire_once 'phing/Task.php';

class MyTask extends Task {/** * (non-PHPdoc) * @see \Task::main() */public function main() {

// Custom code here...}

}

Custom Task (External file)

Phing for power users

Page 49: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="hello">

<target name="init"> <taskdef

name="mytask"classpath="${project.basedir}"classname="MyApp.Common.Phing.MyTask" />

</target>

<target name="hello" depends="init">

<mytask /></target>

</project>

Custom Task (External file)

Phing for power users

Page 50: Phing for power users - frOSCon8

<?phprequire_once 'phing/Task.php';

class MyTask extends Task {protected $file;

/** * @param string $file */public function setFile($file) {

$this->file = $file;}

/** * @see \Task::main() */public function main() {

// Custom code here...}

}

Custom Task with Parameters

Phing for power users

Page 51: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="hello">

<target name="init"> <taskdef

name="mytask"classpath="${project.basedir}"classname="MyApp.Common.Phing.MyTask" />

</target>

<target name="hello" depends="init">

<mytask file="myfile.txt" /></target>

</project>

Custom Task with Parameters

Phing for power users

Page 52: Phing for power users - frOSCon8

Properties File

Phing for power users

Page 53: Phing for power users - frOSCon8

Properties File

Phing for power users

Use properties to cutomize build behaviour.

Page 54: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="hello">

<target name="hello" description="Says whatever you want to say">

<propertyfile="./build.properties" />

 <echo msg="${Hello}" /></target>

</project>

Properties File

Phing for power users

Page 55: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="hello">

<target name="hello" description="Says whatever you want to say">

<propertyfile="./build.properties" />

 <echo msg="${Hello}" /></target>

</project>

Properties File

Phing for power users

Hello=Hello, world!build.properties:

Page 56: Phing for power users - frOSCon8

Properties File

Phing for power users

$> phingBuildfile: /tmp/myproject/build.xml

myproject > hello:

[property] Loading /tmp/myproject/build.properties [echo] Hello, world!

BUILD FINISHED

Total time: 0.0601 seconds

Page 57: Phing for power users - frOSCon8

Properties File - Improved version

Phing for power users

Page 58: Phing for power users - frOSCon8

Properties File - Improved version

Phing for power users

Requirement: Externalize properties but offer customization capabilities!

Page 59: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="hello">

<target name="hello" depends="init"> <echo msg="${Hello}" />

</target>

<target name="init" depends="prop, local-prop"><!-- some more init logic -->

</target>

<target name="prop"><echo

message="Loading default build.properties"/><property

file="build.properties" /></target>

Properties File - Improved version

Phing for power users

Page 60: Phing for power users - frOSCon8

<target name="local-prop"if="local-prop.exists"depends="local-prop-check">

<echo message="Loading custom properties!"/><property

file="local.properties"override="true"/>

</target>

<target name="local-prop-check"><available

file="local.properties"property="local-prop.exists" />

</target></project>

Properties File - Improved version

Phing for power users

Page 61: Phing for power users - frOSCon8

$> phingBuildfile: /tmp/myproject/build.xml

myproject > prop: [echo] Loading default build.properties [property] Loading /tmp/myproject/build.properties

myproject > local-prop-check:

myproject > local-prop:

myproject > init:

myproject > hello: [echo] Hello, world!

BUILD FINISHED

Total time: 0.1383 seconds

Properties File - Improved version

Phing for power users

Page 62: Phing for power users - frOSCon8

$> phingBuildfile: /tmp/myproject/build.xml

myproject > prop: [echo] Loading default build.properties [property] Loading /tmp/myproject/build.properties

myproject > local-prop-check:

myproject > local-prop: [echo] Loading custom properties! [property] Loading /tmp/myproject/local.properties

myproject > init:

myproject > hello: [echo] Hello my world!

BUILD FINISHED

Total time: 0.0493 seconds

Properties File - Improved version

Phing for power users

Page 63: Phing for power users - frOSCon8

build.properties example

Phing for power users

phpunit.path=vendor/bin/phpunitphpunit.junit.log=build/logs/junit.xmlphpunit.coverage.clover=build/logs/clover.xmlphpunit.coverage.html=build/coverage

phpcs.path=vendor/bin/phpcsphpcs.log=build/logs/checkstyle.xml

sencha.senchaCmd=/user/local/lib/sencha/senchasencha.jsb3File=app.jsb3

Page 64: Phing for power users - frOSCon8

build.properties example

Phing for power users

Use distinct naming conventions for your properties.

Page 65: Phing for power users - frOSCon8

Accessing application configuration

Phing for power users

Page 66: Phing for power users - frOSCon8

Accessing application configuration

Phing for power users

Duplicating configuration code is a bad habit.

Page 67: Phing for power users - frOSCon8

Accessing application configuration

Phing for power users

<?phprequire_once 'phing/Task.php';

class ConfigMapperTask extends Task {/** * @see \Task::main() */public function main() {

// will import $APP_CONF in local contextrequire_once('src/bootstrap.php');

$project = $this->project;$project->setProperty(

'db.host', $APP_CONF['db_host']);$project->setProperty(

'db.database', $APP_CONF['db_database']);$project->setProperty(

'db.user', $APP_CONF['db_user']);$project->setProperty(

'db.password', $APP_CONF['db_passwd']);}

}

Page 68: Phing for power users - frOSCon8

Accessing application configuration

Phing for power users

<?xml version="1.0"?><project name="myproject" default="hello">

<taskdef name="readAppConfig"classpath="${phing.dir}/src/"classname="MyApp.Common.Phing.AppConfigTask" />

<target name="init" depends="prop, local-prop"> <readAppConfig />

</target>

<target name="prop"><echo message="Load default build.properties"/><property file="build.properties" />

</target>

<target name="local-prop"if="local-prop.exists"depends="local-prop-check">

<!-- […] --></project>

Page 69: Phing for power users - frOSCon8

Imports for Targets can help structuring

Phing for power users

Page 70: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="app:run">

<!--The following target namespaces exist:db:* - Database specific targetsapp:* - Application specific tasksci:* - CI server specific tasks--><import file="build/build.db.xml" /><import file="build/build.app.xml" /><import file="build/build.ci.xml" />

</project>

Imports for Targets can help structuring

Phing for power users

Page 71: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="app:run">

<!--The following target namespaces exist:lib1:* - Targets imported from lib1lib2:* - Targets imported from lib2app:* - Local application targets--><import file="vendor/vendor1/lib1/build/build.xml" /><import file="vendor/vendor2/lib2/build/build.xml" /><import file="build/build.app.xml" />

</project>

Import Targets: Composer packages

Phing for power users

Page 72: Phing for power users - frOSCon8

Import Targets: Path handling

Phing for power users

Be aware that imports behave like include in PHP!

Page 73: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="lib1:run">

<!--The following target namespaces exist:lib1:* - Targets imported from lib1--><import file="vendor/lib1/build/build.xml" />

</project>

Import Targets: Path handling

Phing for power users

build.xml

Page 74: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="lib1" default="lib1:run">

<target name="lib1:run">

<echo msg="Local dir: ${phing.dir.lib1}" />

<echo msg="Global dir: ${phing.dir}" /></target>

</project>

<?xml version="1.0"?><project name="myproject" default="lib1:run">

<!--The following target namespaces exist:lib1:* - Targets imported from lib1--><import file="vendor/lib1/build/build.xml" />

</project>

Import Targets: Path handling

Phing for power users

build.xml

vendor/lib1/build/build.xml

Page 75: Phing for power users - frOSCon8

$> ./vendor/bin/phingBuildfile: /tmp/myproject/build.xml

myproject > lib1:run:

[echo] Local dir: /tmp/myproject/vendor/lib1/build [echo] Global dir: /tmp/myproject

BUILD FINISHED

Total time: 0.0411 seconds

Import Targets: Path handling

Phing for power users

Page 76: Phing for power users - frOSCon8

Import Targets: Path handling

Phing for power users

Be aware to always(!) use the projects name in lowercase format!

Page 77: Phing for power users - frOSCon8

Import Targets: Path handling

Phing for power users

It`s ${phing.dir.myproject} not ${phing.dir.MyProject}!

Page 78: Phing for power users - frOSCon8

Distinct Target Naming

Phing for power users

Page 79: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="ci:run-tests">

<target name="app:clean-cache"></target>

<target name="app:create-cache"></target>

<target name="db:migrate"></target>

<target name="js:minifiy"></target>

<target name="ci:lint"></target>

<target name="ci:run-tests"></target>

</project>

Distinct Target Naming

Phing for power users

Page 80: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="app:create-cache">

<target name="app:clean-cache" description="Removes all cache files."></target>

<target name="app:create-cache" description="Builds the cache files from the

xml configuration."></target>

</project>

Adding meaningful descriptions

Phing for power users

Page 81: Phing for power users - frOSCon8

$> phing -lBuildfile: /tmp/myproject/build.xmlDefault target:----------------------------------------------------- app:create-cache Builds the cache files from the xml configuration.

Main targets:------------------------------------------------------ app:clean-cache Removes all cache files. app:create-cache Builds the cache files from the xml configuration.

Adding meaningful descriptions

Phing for power users

Page 82: Phing for power users - frOSCon8

Prompt user for input

Phing for power users

<?xml version="1.0"?><project name="myproject" default="run">

<target name="run"> <!-- tag the database -->

<input propertyname="tag" defaultValue="mytag">Tag to create?</input>

<liquibase-tag tag="${tag}" jar="/opt/liquibase/liquibase.jar" classpathref="/opt/liquibase/lib/mysql.jar" changelogFile="${project.basedir}/diff.xml" username="liquibase" password="liquibase" url="jdbc:mysql://localhost/myproject"/>

</target></project>

Page 83: Phing for power users - frOSCon8

Calling PHP functions from Phing

Phing for power users

Page 84: Phing for power users - frOSCon8

Calling PHP functions from Phing

Phing for power users

<?xml version="1.0"?><project name="myproject" default="run">

<target name="run">

<!-- Returns canonicalized absolute pathname -->

<php function="realpath" returnProperty="app.dir">

<param value="${app.dir}"/> </php></target>

</project>

Page 85: Phing for power users - frOSCon8

Restrict user access

Phing for power users

Page 86: Phing for power users - frOSCon8

<?xml version="1.0"?><project name="myproject" default="run">

<target name="run">

<!-- Check for root user -->

<if> <not> <equals arg1="${env.USER}"

arg2="root" /> </not> <then> <fail message="Wrong user!" /> </then>

</if></target>

</project>

Restrict user access

Phing for power users

Page 87: Phing for power users - frOSCon8

Path handling

Phing for power users

Page 88: Phing for power users - frOSCon8

Path handling

Phing for power users

<?xml version="1.0"?><project name="myproject" default="ci:phpunit">

<!-- ... --><target name="ci:phpunit"

depends="-init, -ci:prepare">

<resolvepath propertyName="phpunit.path.abs" dir="${phing.dir}" file="${phpunit.path}"/>

<exec executable="${phpunit.path.abs}" /></target>

</project>

Page 89: Phing for power users - frOSCon8

Phing + Jenkins

Phing for power users

Page 90: Phing for power users - frOSCon8

Phing + Jenkins

Phing for power users

Install the Jenkins Phing plugin

Page 91: Phing for power users - frOSCon8

Phing for power users

Page 92: Phing for power users - frOSCon8

Phing for power users

Page 93: Phing for power users - frOSCon8

Phing for power users

Page 94: Phing for power users - frOSCon8

Phing + Composer + Jenkins

Phing for power users

Page 95: Phing for power users - frOSCon8

Phing + Composer + Jenkins

Phing for power users

Install the Jenkins EnvInject plugin

Page 96: Phing for power users - frOSCon8

Phing for power users

Page 97: Phing for power users - frOSCon8

Phing for power users

Page 98: Phing for power users - frOSCon8

Phing for power users

Page 99: Phing for power users - frOSCon8

Phing for power users

Page 100: Phing for power users - frOSCon8

Follow conventions

Phing for power users

Page 101: Phing for power users - frOSCon8

Follow conventions

Phing for power users

Phing expects your build file to be called build.xml and the build’s properties file

build.properties

Page 102: Phing for power users - frOSCon8

Follow conventions

Phing for power users

Pick meaningful, human-readable names for targets and properties.

Page 103: Phing for power users - frOSCon8

Follow conventions

Phing for power users

Make build files self-contained.

Page 104: Phing for power users - frOSCon8

Thank you!

Page 105: Phing for power users - frOSCon8

http://joind.in/9023

Page 106: Phing for power users - frOSCon8

Phing for power users

Image Credits

http://www.sxc.hu/photo/629370http://www.sxc.hu/photo/615731