Phing for power users - frOSCon8
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
840
On Slideshare
746
From Embeds
94
Number of Embeds
4

Actions

Shares
Downloads
6
Comments
0
Likes
2

Embeds 94

http://blog.loc 51
http://blog.staging.bitexpert.net 40
http://dex.io 2
http://blog.bitexpert.de 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Phing for power users Stephan Hochdörfer, bitExpert AG
  • 2. Phing for power users About me  Stephan Hochdörfer  Head of IT at bitExpert AG, Germany  enjoying PHP since 1999  S.Hochdoerfer@bitExpert.de  @shochdoerfer
  • 3. Phing for power users I used to be an Ant fanboy...
  • 4. What is Phing? Phing for power users
  • 5. What is Phing? Phing for power users It is a PHP project build system or build tool based on Apache Ant.
  • 6. What is Phing? Phing for power users Domain Specific Language for an project build system.
  • 7. Phing for power users A build system for PHP code? Srsly?
  • 8. Glue for all 3rd party tools Phing for power users
  • 9. How to install Phing? Phing for power users
  • 10. $> pear channel­discover pear.phing.info $> pear install phing/phing How to install Phing? The PEAR way... Phing for power users Installing Phing
  • 11. $> phing ­v Phing 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:
  • 12. How to install Phing? Phing for power users Installing Phing globally? WTF?!?
  • 13. How to install Phing? Phing for power users Phing is „just another“ dependency for your project.
  • 14. How to install Phing? The Composer way... Phing for power users
  • 15. { "require": { "phing/phing": "2.5.0" } } How to install Phing? The Composer way... Phing for power users composer.json:
  • 16. { "require": { "phing/phing": "2.5.0" } } $> php composer.phar install Loading composer repositories with package information Installing dependencies   ­ Installing phing/phing (2.5.0)     Downloading: 100%          Writing lock file Generating autoload files How to install Phing? The Composer way... Phing for power users composer.json: Running Composer:
  • 17. 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
  • 18. 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 ­v Phing 2.5.0 Running Phing:
  • 19. Phing Basics Phing for power users
  • 20. Phing Basics Phing for power users Project, Target, Task, Properties
  • 21. Phing Basics: Project Phing for power users Root node of a build file containing one or more targets.
  • 22. Phing Basics: Target Phing for power users A group of tasks that run as an entity.
  • 23. Phing Basics: Task Phing for power users Custom piece of code to perform a specific function.
  • 24. Phing Basics: Properties Phing for power users Properties (variables) help to customize execution.
  • 25. Phing Basics: Built-In Properties Phing for power users e.g. host.os, line.separator, phing.version, php.version, …
  • 26. <?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
  • 27. <?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
  • 28. Why Phing? Phing for power users Runs everywhere where PHP runs.
  • 29. Why Phing? Phing for power users No additional depencendies needed (e.g. Java, …).
  • 30. Why Phing? Phing for power users More than 120 predefined tasks to choose from.
  • 31. Why Phing? Phing for power users Easy to extend by writing custom tasks in PHP.
  • 32. Enforce Internal Targets Phing for power users
  • 33. 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>
  • 34. 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
  • 35. 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
  • 36. Enforce Internal Targets Phing for power users $> ./vendor/bin/phing -l Buildfile: /tmp/myproject/build.xml Default target: --------------------------------------------------------- hello Main targets: --------------------------------------------------------- init Property initialization Subtargets: --------------------------------------------------------- hello
  • 37. Enforce Internal Targets Phing for power users Internal targets are just helpers like private methods.
  • 38. <?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
  • 39. Enforce Internal Targets – The solution Phing for power users $> ./vendor/bin/phing -f build.xml -init Unknown argument: -init phing [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 <dev@phing.tigris.org>
  • 40. Enforce Internal Targets – The solution Phing for power users Are the targets really hidden?
  • 41. Enforce Internal Targets Phing for power users $> ./vendor/bin/phing -l Buildfile: /tmp/myproject/build.xml Default target: --------------------------------------------------------- hello Main targets: --------------------------------------------------------- -init Property initialization Subtargets: --------------------------------------------------------- hello
  • 42. Enforce Internal Targets Phing for power users $> ./vendor/bin/phing -l Buildfile: /tmp/myproject/build.xml Default target: --------------------------------------------------------- hello Main targets: --------------------------------------------------------- -init Property initialization Subtargets: --------------------------------------------------------- hello
  • 43. 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>
  • 44. $> ./vendor/bin/phing -l Buildfile: /tmp/myproject/build.xml Default target: --------------------------------------------------------- hello Subtargets: --------------------------------------------------------- hello Enforce Internal Targets (Improved Version) Phing for power users
  • 45. Custom Tasks Phing for power users
  • 46. Custom Tasks Phing for power users Phing can do way more than simple exec calls!
  • 47. 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>
  • 48. <?php require_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
  • 49. <?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
  • 50. <?php require_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
  • 51. <?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
  • 52. Properties File Phing for power users
  • 53. Properties File Phing for power users Use properties to cutomize build behaviour.
  • 54. <?xml version="1.0"?> <project name="myproject" default="hello"> <target name="hello"  description="Says whatever you want to say"> <property file="./build.properties" />  <echo msg="${Hello}" /> </target> </project> Properties File Phing for power users
  • 55. <?xml version="1.0"?> <project name="myproject" default="hello"> <target name="hello"  description="Says whatever you want to say"> <property file="./build.properties" />  <echo msg="${Hello}" /> </target> </project> Properties File Phing for power users Hello=Hello, world! build.properties:
  • 56. Properties File Phing for power users $> phing Buildfile: /tmp/myproject/build.xml myproject > hello: [property] Loading /tmp/myproject/build.properties [echo] Hello, world! BUILD FINISHED Total time: 0.0601 seconds
  • 57. Properties File - Improved version Phing for power users
  • 58. Properties File - Improved version Phing for power users Requirement: Externalize properties but offer customization capabilities!
  • 59. <?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
  • 60. <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
  • 61. $> phing Buildfile: /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
  • 62. $> phing Buildfile: /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
  • 63. build.properties example Phing for power users phpunit.path=vendor/bin/phpunit phpunit.junit.log=build/logs/junit.xml phpunit.coverage.clover=build/logs/clover.xml phpunit.coverage.html=build/coverage phpcs.path=vendor/bin/phpcs phpcs.log=build/logs/checkstyle.xml sencha.senchaCmd=/user/local/lib/sencha/sencha sencha.jsb3File=app.jsb3
  • 64. build.properties example Phing for power users Use distinct naming conventions for your properties.
  • 65. Accessing application configuration Phing for power users
  • 66. Accessing application configuration Phing for power users Duplicating configuration code is a bad habit.
  • 67. Accessing application configuration Phing for power users <?php require_once 'phing/Task.php'; class ConfigMapperTask extends Task { /** * @see Task::main() */ public function main() { // will import $APP_CONF in local context require_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']); } }
  • 68. 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>
  • 69. Imports for Targets can help structuring Phing for power users
  • 70. <?xml version="1.0"?> <project name="myproject" default="app:run"> <!-- The following target namespaces exist: db:* - Database specific targets app:* - Application specific tasks ci:* - 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
  • 71. <?xml version="1.0"?> <project name="myproject" default="app:run"> <!-- The following target namespaces exist: lib1:* - Targets imported from lib1 lib2:* - Targets imported from lib2 app:* - 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
  • 72. Import Targets: Path handling Phing for power users Be aware that imports behave like include in PHP!
  • 73. <?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
  • 74. <?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
  • 75. $> ./vendor/bin/phing Buildfile: /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
  • 76. Import Targets: Path handling Phing for power users Be aware to always(!) use the projects name in lowercase format!
  • 77. Import Targets: Path handling Phing for power users It`s ${phing.dir.myproject} not ${phing.dir.MyProject}!
  • 78. Distinct Target Naming Phing for power users
  • 79. <?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
  • 80. <?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
  • 81. $> phing -l Buildfile: /tmp/myproject/build.xml Default 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
  • 82. 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>
  • 83. Calling PHP functions from Phing Phing for power users
  • 84. 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>
  • 85. Restrict user access Phing for power users
  • 86. <?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
  • 87. Path handling Phing for power users
  • 88. 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>
  • 89. Phing + Jenkins Phing for power users
  • 90. Phing + Jenkins Phing for power users Install the Jenkins Phing plugin
  • 91. Phing for power users
  • 92. Phing for power users
  • 93. Phing for power users
  • 94. Phing + Composer + Jenkins Phing for power users
  • 95. Phing + Composer + Jenkins Phing for power users Install the Jenkins EnvInject plugin
  • 96. Phing for power users
  • 97. Phing for power users
  • 98. Phing for power users
  • 99. Phing for power users
  • 100. Follow conventions Phing for power users
  • 101. Follow conventions Phing for power users Phing expects your build file to be called build.xml and the build’s properties file build.properties
  • 102. Follow conventions Phing for power users Pick meaningful, human-readable names for targets and properties.
  • 103. Follow conventions Phing for power users Make build files self-contained.
  • 104. Thank you!
  • 105. http://joind.in/9023
  • 106. Phing for power users Image Credits http://www.sxc.hu/photo/629370 http://www.sxc.hu/photo/615731