Build Automation with Phive and Phing

Build Automation with Phive and Phing

PHPUG Cologne 2018-06-01

3f2fb8bbcd44609346e1cc0c06d0a39b?s=128

Thomas Weinert

June 01, 2018
Tweet

Transcript

  1. BUILD AUTOMATION BUILD AUTOMATION WITH PHIVE AND PHING WITH PHIVE

    AND PHING @ThomasWeinert
  2. TOOLS FOR PHP TOOLS FOR PHP PHPUnit Phing phpDocumentor phpcs

    ...
  3. TOOLS FOR A PROJECT TOOLS FOR A PROJECT Which tool?

    Which version? How to call? What to do next?
  4. None
  5. COMPOSER COMPOSER Project dependency management Dependency conflicts!

  6. PHIVE PHIVE Tool dependency management Phar packages GPG signatures

  7. INSTALL PHIVE INSTALL PHIVE > wget https://phar.io/releases/phive.phar > wget https://phar.io/releases/phive.phar.asc

    > gpg --keyserver hkps.pool.sks-keyservers.net --recv-keys 0x9 > gpg --verify phive.phar.asc phive.phar > chmod +x phive.phar > sudo mv phive.phar /usr/bin/phive Shell
  8. THE FIRST CONTACT THE FIRST CONTACT > git checkout git@example.tld:awesome-project.git

    > cd awesome-project > phive install Shell
  9. GPG SIGNATURES GPG SIGNATURES

  10. TOOLS AVAILABLE TOOLS AVAILABLE

  11. PHIVE BASIC USAGE PHIVE BASIC USAGE phive install phive install

    tool-name phive update
  12. BUILD TARGETS/GOALS BUILD TARGETS/GOALS Setup Update Deployment ...

  13. PHING PHING based on Apache Ant Phar, installable using Phive

    IDE integration (PHPStorm, Netbeans, Eclipse) XML build file Extendable via PHP
  14. IDE INTEGRATION (PHPSTORM) IDE INTEGRATION (PHPSTORM)

  15. CODE COMPLETION CODE COMPLETION

  16. THE FIRST CONTACT II THE FIRST CONTACT II > git

    checkout git@example.tld:awesome-project.git > cd awesome-project > phive install > tools/phing Shell
  17. COMPOSER PROJECT EXAMPLE COMPOSER PROJECT EXAMPLE > composer create-project someone/awesome-project

    new-project > cd new-project > phive install > tools/phing > git init && git add * && git commit -m"new project" > tools/phing run Shell
  18. None
  19. PHING TARGETS PHING TARGETS

  20. HELLO WORLD HELLO WORLD <project name="A Project" default="build"> <target name="build">

    <echo message="Hello World!"/> </target> </project> XML
  21. A Project > build: [echo] Hello World! BUILD FINISHED Shell

  22. A PROPERTY A PROPERTY <project name="A Project" default="build"> <property name="database.user"

    value="username"/> <target name="build"> <echo message="Database User: ${database.user}"/> </target> </project> XML
  23. A Project > build: [echo] Database User: username BUILD FINISHED

    Shell
  24. PROPERTIES FILE PROPERTIES FILE <project name="A Project" default="build"> <property file="build.properties"

    prefix="configuration"/> <property name="database.user" value="${configuration.database.user}"/> <target name="build"> <echo message="Database User: ${database.user}"/> </target> </project> XML
  25. # Database Configuration database.user=a-user database.password=secret build.properties

  26. [property] Loading /path/build.properties A Project > build: [echo] Database User:

    a-user BUILD FINISHED Shell
  27. DISTRIBUTED PROPERTIES FILE DISTRIBUTED PROPERTIES FILE <project name="A Project" default="build">

    <property file="dist.build.properties" prefix="configuration"/> <property file="build.properties" prefix="configuration" override="true"/> <property name="database.user" value="${configuration.database.user}"/> <!--...--> </project> XML
  28. # Database Configuration database.user=default-user database.password=secret dist.build.properties

  29. [property] Loading /path/dist.build.properties [property] Loading /path/build.properties [property] Unable to find

    property file: /path/build.properties... skipped A Project > build: [echo] Database User: default-user BUILD FINISHED Shell
  30. FILES & DIRECTORIES FILES & DIRECTORIES

  31. FILESET FILESET <fileset id="dependencies" dir="${directory.src}"> <include name="composer.json"/> <include name="composer.lock"/> </fileset>

    XML <fileset id="public" dir="${directory.document-root}"> <include name="**"/> <exclude name="**/.git/**"/> </fileset> XML
  32. COPY COPY <target name="build"> <copy todir="${directory.export}/source/htdocs"> <fileset refid="public"/> </copy> <copy

    todir="${directory.export}/source"> <fileset refid="dependencies"/> </copy> </target> XML
  33. CREATE DIRECTORY CREATE DIRECTORY <property name="mode.writeable" value="0777"/> <target name="prepare"> <mkdir

    dir="${directory.src}/data/cache" mode="${mode.writeable}"/> <mkdir dir="${directory.src}/data/media/files" mode="${mode.writeable}"/> <mkdir dir="${directory.src}/data/media/thumbs" mode="${mode.writeable}"/> </target> XML
  34. REMOVE REMOVE <target name="clean-build"> <delete dir="${directory.export}/source"/> </target> XML <target name="clean-archives">

    <delete> <fileset refid="archives"/> </delete> </target> XML
  35. TARGETS TARGETS

  36. DEPENDENCIES DEPENDENCIES <target name="build" depends="prepare"/> <target name="prepare"> <echo message="Hello World!"/>

    </target> XML
  37. A Project > prepare: [echo] Hello World! A Project >

    build: BUILD FINISHED Shell
  38. DESCRIPTIONS DESCRIPTIONS <target name="build" depends="prepare" description="Build project"/> <target name="prepare"> <echo

    message="Hello World!"/> </target> XML
  39. None
  40. HIDDEN HIDDEN <target name="build" depends="prepare" description="Build project"/> <target name="prepare" hidden="yes">

    <echo message="Hello World!"/> </target> XML
  41. None
  42. TEMPLATE FILE TEMPLATE FILE

  43. template.configuration.php template.configuration.php <?php define('DATABASE_URI', '${database.uri}'); PHP

  44. EXPAND PROPERTIES EXPAND PROPERTIES <property name="config.template" value="${project.basedir}/template.configuration.php" /> <property name="config.file"

    value="${project.basedir}/configuration.php"/> <property name="database.uri" value="sqlite3://project.sqlite" /> <copy file="${config.template}" tofile="${config.file}"> <filterchain> <expandproperties/> </filterchain> </copy> XML
  45. FILTERS FILTERS replacetokens replaceregexp xsltfilter ...

  46. CONDITION CONDITION <condition property="directorySeparator" value="\" else="/"> <os family="windows"/> </condition> <echo

    message="Directory Separator: ${directorySeparator}"/> XML
  47. FILE EXISTS FILE EXISTS <property name="hasConfiguration" value="false"/> <available file="${config.file}" property="hasConfiguration"

    value="true"/> XML
  48. CONDITION CONDITION <if> <isfalse value="${hasConfiguration}"/> <then> <copy file="${config.template}" tofile="${config.file}"> <filterchain>

    <expandproperties/> </filterchain> </copy> </then> <else> <warn message="configuration.php already exists. Skipped."/> </else> </if> XML
  49. RUN 1 RUN 1 A Project > build: [copy] Copying

    1 file to /project/path/ BUILD FINISHED Shell
  50. RUN 2 RUN 2 A Project > build: [warn] configuration.php

    already exists. Skipped. BUILD FINISHED Shell
  51. EXECUTE TOOLS EXECUTE TOOLS

  52. COMPOSER INSTALL COMPOSER INSTALL <exec executable="composer" passthru="true"> <arg value="-n"/> <arg

    value="install"/> </exec> XML
  53. GIT TAG GIT TAG <property name="revision" value="dev"/> <exec executable="git" dir="${project.basedir}"

    returnProperty="git.return" outputProperty="git.output"> <arg line="describe --tags"/> </exec> <if> <equals arg1="${git.return}" arg2="0"/> <then> <property name="revision" value="${git.output}" override="true"/> </then> </if> XML
  54. GIT DESCRIBE GIT DESCRIBE A Project > project-revision: [echo] Project

    revision: 4.0.1-14-g7597c11 BUILD FINISHED Shell
  55. PHP BUILTIN WEBSERVER PHP BUILTIN WEBSERVER <exec executable="php" passthru="true"> <arg

    line="-S localhost:8080 -t ./htdocs server.php"/> </exec> XML
  56. COMPOSER PACKAGE VERSION COMPOSER PACKAGE VERSION

  57. DEFINE ADHOC TASK DEFINE ADHOC TASK <adhoc-task name="composer-version"> <![CDATA[ class

    AVersionTask extends Task { function main() { $json = json_decode(file_get_contents("composer.lock")); foreach ($json->packages as $package) { if ($package->name === 'carica/io') { $this->project->setProperty( 'revision', $package->version.' '.substr($package->source->reference, 0, 8) ); } } } } XML
  58. USE ADHOC TASK USE ADHOC TASK <property name="revision" value=""/> <trycatch

    property="error"> <try> <adhoc-task name="composer-version">...</adhoc-task> <composer-version/> <echo message="Revision: ${revision}"/> </try> <catch> <echo level="warning">There was an error...</echo> <echo level="debug">${error}</echo> <property name="revision" value="unknown" override="true"/> </catch> </trycatch> XML
  59. A Project > package-revision: [echo] Revision: 1.0.0 8f996060 BUILD FINISHED

    Shell
  60. A Project > package-revision: [PHP Error] file_get_contents(composer.lock): failed to open

    s [PHP Error] Invalid argument supplied for foreach() [line 6 of [echo] Revision: BUILD FINISHED Shell