Phing All The Things!
Omni Adams

Lazy development

sleeping cat

Stay DRY

http://ardalis.com/DRY---Don%E2%80%99t-Repeat-Yourself---Motivator
    <?xml version="1.0" encoding="UTF-8"?>
    <project name="phing-the-things" default="test">
        <target name="test">
            <exec executable="phpunit" passthru="true"
                    checkreturn="true" />
        </target>
    </project>
    <?xml version="1.0" encoding="UTF-8"?>
    <project name="phing-the-things" default="test">
        <target name="test">
            <exec executable="phpunit" passthru="true"
                    checkreturn="true" />
        </target>
    </project>
    <?xml version="1.0" encoding="UTF-8"?>
    <project name="phing-the-things" default="test">
        <target name="test">
            <exec executable="phpunit" passthru="true"
                    checkreturn="true" />
        </target>
    </project>
    <?xml version="1.0" encoding="UTF-8"?>
    <project name="phing-the-things" default="test">
        <target name="test">
            <exec executable="phpunit" passthru="true"
                    checkreturn="true" />
        </target>
    </project>
    <?xml version="1.0" encoding="UTF-8"?>
    <project name="phing-the-things" default="test">
        <target name="test">
            <exec executable="phpunit" passthru="true"
                    checkreturn="true" />
        </target>
    </project>
phing-the-things$ phing test
Buildfile: /Users/Omni/phing-example/build.xml
 [property] Loading /Users/Omni/phing-example/build.properties

phing-example > test:

PHPUnit 3.7.13 by Sebastian Bergmann.

Configuration read from /Users/Omni/phing-example/phpunit.xml

..............................
Time: 0 seconds, Memory: 7.25Mb

OK (30 tests, 52 assertions)

BUILD FINISHED
Total time: 0.3155 seconds
F.............................
Time: 0 seconds, Memory: 7.25Mb

There was 1 failure:

1) GitTest::testGetCommitInfo
LOL cats have clogged the tubes!
/Users/Omni/phing-example/tests/GitTest.php:51

FAILURES!
Tests: 30, Assertions: 51, Failures: 1.
Execution of target "test" failed for the following reason: /Users/Omni/phing-example/build.xml:102:46: Task exited with code 1

BUILD FAILED
/Users/Omni/phing-example/build.xml:102:46: Task exited with code 1
Total time: 0.5653 seconds
    <?xml version="1.0" encoding="UTF-8"?>
    <project name="phing-the-things" default="test">
        <target name="test">
            <exec executable="phpunit" passthru="true"
                    checkreturn="true" />
        </target>
    </project>
    <?xml version="1.0" encoding="UTF-8"?>
    <project name="phing-the-things" default="test">
        <target name="test">
            <exec executable="phpunit" passthru="true"
                    checkreturn="true" />
        </target>
    </project>
F.............................

Time: 0 seconds, Memory: 7.25Mb

There was 1 failure:

1) GitTest::testGetCommitInfo
LOL cats have clogged the tubes!

/Users/Omni/phing-example/tests/GitTest.php:51

FAILURES!
Tests: 30, Assertions: 51, Failures: 1.

BUILD FINISHED

Total time: 0.5619 seconds
LOLWUT?
    <target name="test">
        <exec executable="phpunit" passthru="true"
                checkreturn="true">
            <arg value="--exclude-group=integration" />
        </exec>
    </target>
    <target name="test">
        <exec executable="phpunit" passthru="true"
                checkreturn="true">
            <arg value="${phpunitFlag}" />
        </exec>
    </target>
Find X
    <property name="phpunitFlag" value="--group=smoke" />
phing-the-things$ phing test -DphpunitFlag=--group=smoke
Buildfile: /Users/Omni/phing-example/build.xml
 [property] Loading /Users/Omni/phing-example/build.properties

phing-example > test:

PHPUnit 3.7.13 by Sebastian Bergmann.

Configuration read from /Users/Omni/phing-example/phpunit.xml

........
Time: 0 seconds, Memory: 7.25Mb

OK (8 tests, 12 assertions)

BUILD FINISHED
Total time: 0.1058 seconds
composer=/opt/composer.phar
server1.user=oadams
server1.url=www.example.lan
    <property file="build.properties" />
    <target name="properties-example">
        <exec executable="${composer}" />
        <exec executable="ssh" passthru="true">
            <arg value="-t" />
            <arg value="${server1.user}@${server1.url}" />
            <arg value="sudo /sbin/service httpd restart" />
        </exec>
    </target>
first
things
first
# build.properties
foo=test
bar=test
    <property name="foo" value="bar" />
    <property file="build.properties" />
    <property name="mitz" value="fah" />
Smelly feet
    <patternset id="files">
        <include name="**/*.php" />
        <exclude name="third-party/**" />
        <exclude name="vendor/**" />
    </patternset>
    <target name="phpcs">
        <phpcodesniffer standard="./coding_rules.xml" format="full"
                showWarnings="true">
            <fileset dir=".">
                <patternset refid="files" />
            </fileset>
        </phpcodesniffer>
    </target>
Documentation
    <target name="document" depends="require-docdir">
        <mkdir dir="${docdir}/api" />
        <exec executable="phpdoc" passthru="true">
            <arg value="--directory=." />
            <arg value="--ignore=vendor/*" />
            <arg value="--ignore=src/*" />
            <arg value="--progressbar" />
            <arg value="--target=${docdir}/api" />
            <arg value="--title=API documentation" />
        </exec>
    </target>
    <target name="document" depends="require-docdir">
        <mkdir dir="${docdir}/api" />
        <exec executable="phpdoc" passthru="true">
            <arg value="--directory=." />
            <arg value="--ignore=vendor/*" />
            <arg value="--ignore=src/*" />
            <arg value="--progressbar" />
            <arg value="--target=${docdir}/api" />
            <arg value="--title=API documentation" />
        </exec>
    </target>
    <target name="document" depends="require-docdir">
        <mkdir dir="${docdir}/api" />
        <exec executable="phpdoc" passthru="true">
            <arg value="--directory=." />
            <arg value="--ignore=vendor/*" />
            <arg value="--ignore=src/*" />
            <arg value="--progressbar" />
            <arg value="--target=${docdir}/api" />
            <arg value="--title=API documentation" />
        </exec>
    </target>
    <target name="document" depends="require-docdir">
        <mkdir dir="${docdir}/api" />
        <exec executable="phpdoc" passthru="true">
            <arg value="--directory=." />
            <arg value="--ignore=vendor/*" />
            <arg value="--ignore=src/*" />
            <arg value="--progressbar" />
            <arg value="--target=${docdir}/api" />
            <arg value="--title=API documentation" />
        </exec>
    </target>
    <exec executable="ps" outputProperty="ps-output">
        <arg value="x" />
        <arg value="|" />
        <arg value="grep" />
        <arg value="selenium" />
        <arg value="|" />
        <arg value="grep" />
        <arg value="-v" />
        <arg value="grep" />
        <arg value="|" />
        <arg value="grep" />
        <arg value="-v" />
        <arg value="phing" />
    </exec>
     <exec executable="ps" outputProperty="ps-output">
        <arg line="x | grep selenium | grep -v grep | grep -v phing" />
    </exec>
Don't cross the streams
Jenga game falling over
Dependency graph
    <target name="build" depends="test" />

    <target name="coverage-html" depends="require-docdir">
        <exec executable="phpunit" passthru="true">
            <arg value="--coverage-html=${docdir}/coverage" />
            <arg value="${phpunitFlag}" />
        </exec>
    </target>
     <target name="require-docdir">
        <if>
            <not>
                <isset property="docdir" />
            </not>
            <then>
                <fail message="docdir isn't set in your build.properties file" />
            </then>
        </if>
    </target>
    <property name="foo" value="bar" />
    <target name="example" depends="other-task">
        <phingcall target="other-task">
            <property name="foo" value="test" />
            <property name="baz" value="test" />
        </phingcall>
        <phingcall target="other-task" />
    </target>
    <target name="other-task">
        <echo message="${foo}" />
        <echo message="${baz}" />
    </target>
Lazy cat
    <uptodate property="css-compiled" targetfile="style.css">
        <srcfiles dir="styles" includes="**/*less" />
    </uptodate>
    <uptodate property="css-compiled" targetfile="style.css">
        <srcfiles dir="styles" includes="**/*less" />
    </uptodate>
    <uptodate property="css-compiled" targetfile="style.css">
        <srcfiles dir="styles" includes="**/*less" />
    </uptodate>
    <uptodate property="css-compiled" targetfile="style.css">
        <srcfiles dir="styles" includes="**/*less" />
    </uptodate>
    <uptodate property="css-compiled" targetfile="style.css">
        <srcfiles dir="styles" includes="**/*less" />
    </uptodate>
    <uptodate property="css-compiled" targetfile="style.css">
        <srcfiles dir="styles" includes="**/*less" />
    </uptodate>
    <target name="compile-css" unless="css-compiled">
        <exec executable="lessc" passthru="true" checkreturn="true">
            <arg value="-x" />
            <arg value="styles/*.less" />
            <arg value="style.css" />
        </exec>
    </target>
Composer logo
    <available property="composer-exists" file="composer.phar" />
    <target name="get-composer" unless="composer-exists">
        <exec executable="curl" output="composer.php">
            <arg value="-sS" />
            <arg value="https://getcomposer.org/installer" />
            <arg value="|" />
            <arg value="php" />
        </exec>
        <chmod file="composer.phar" perm="664" />
    </target>
    <available property="composer-exists" file="composer.phar" />
    <target name="get-composer" unless="composer-exists">
        <exec executable="curl" output="composer.php">
            <arg value="-sS" />
            <arg value="https://getcomposer.org/installer" />
            <arg value="|" />
            <arg value="php" />
        </exec>
        <chmod file="composer.phar" perm="664" />
    </target>
Deployment
assumptions
Paranoia
Tags
    <target name="tag" depends="require-version">
        <gittag annotate="true" name="${version}" repository="."
                message="Tagged version ${version}" />
        <gitpush repository="." tags="true" quiet="true" />
    </target>
phing-the-things$ phing tag
Buildfile: /Users/Omni/Sites/phing/build.xml
 [property] Loading /Users/Omni/Sites/phing/build.properties

phing-the-things > require-version:

       [if] Error in IfTask
Execution of target "require-version" failed for the following reason: /Users/Omni/Sites/phing/build.xml:146:12: /Users/Omni/Sites/phing/build.xml:150:18: You must pass in a version: -Dversion=1.2.3
BUILD FAILED
/Users/Omni/Sites/phing/build.xml:146:12: /Users/Omni/Sites/phing/build.xml:150:18: You must pass in a version: -Dversion=1.2.3
Total time: 1.5921 second
phing-the-things$ phing tag-no-version
Buildfile: /Users/Omni/Sites/phing/build.xml
 [property] Loading /Users/Omni/Sites/phing/build.properties

phing-the-things > tag-no-version:

   [gittag] git-tag command: /usr/bin/git tag -a -m'Tagged version ${version}' '${version}'
   [gittag] git-tag: tags for "." repository
   [gittag] git-tag output:

BUILD FINISHED

Total time: 0.2039 seconds

phing-the-things $ git tag
${version}
    <target name="tag-version">
        <version releasetype="${release}" file="version.txt" property="version" />
        <exec executable="git" passthru="true">
            <arg line="add version.txt" />
        </exec>
        <exec executable="git" passthru="true">
            <arg line="commit -m 'Updated version file to ${version}'" />
        </exec>
        <gittag annotate="true" name="${version}" repository="."
                message="Tagged version ${version}" />
    </target>
    <target name="tag-version">
        <version releasetype="${release}" file="version.txt" property="version" />
        <exec executable="git" passthru="true">
            <arg line="add version.txt" />
        </exec>
        <exec executable="git" passthru="true">
            <arg line="commit -m 'Updated version file to ${version}'" />
        </exec>
        <gittag annotate="true" name="${version}" repository="."
                message="Tagged version ${version}" />
    </target>
    <target name="tag-version">
        <version releasetype="${release}" file="version.txt" property="version" />
        <exec executable="git" passthru="true">
            <arg line="add version.txt" />
        </exec>
        <exec executable="git" passthru="true">
            <arg line="commit -m 'Updated version file to ${version}'" />
        </exec>
        <gittag annotate="true" name="${version}" repository="."
                message="Tagged version ${version}" />
    </target>
    <target name="tag-version">
        <version releasetype="${release}" file="version.txt" property="version" />
        <exec executable="git" passthru="true">
            <arg line="add version.txt" />
        </exec>
        <exec executable="git" passthru="true">
            <arg line="commit -m 'Updated version file to ${version}'" />
        </exec>
        <gittag annotate="true" name="${version}" repository="."
                message="Tagged version ${version}" />
    </target>
    <target name="tag-version">
        <version releasetype="${release}" file="version.txt" property="version" />
        <exec executable="git" passthru="true">
            <arg line="add version.txt" />
        </exec>
        <exec executable="git" passthru="true">
            <arg line="commit -m 'Updated version file to ${version}'" />
        </exec>
        <gittag annotate="true" name="${version}" repository="."
                message="Tagged version ${version}" />
    </target>
phing-the-things$ phing tag-version -Drelease=minor
Buildfile: /Users/Omni/Sites/phing/build.xml
 [property] Loading /Users/Omni/Sites/phing/build.properties
phing-the-things > tag-version:

[master 4b48e9f] Updated version file to 0.1.0
 1 file changed, 1 insertion(+), 1 deletion(-)
   [gittag] git-tag command: /usr/bin/git tag -a -m'Tagged version 0.1.0' '0.1.0'
   [gittag] git-tag: tags for "." repository
   [gittag] git-tag output:

BUILD FINISHED
Total time: 0.3507 seconds

phing-the-things $ git tag
0.0.1
0.1.0
    <target name="release-major">
        <phingcall target="tag-version">
            <property name="release" value="major" />
        </phingcall>
    </target>
    <target name="release-minor">
        <phingcall target="tag-version">
            <property name="release" value="minor" />
        </phingcall>
    </target>
    <target name="tag-svn">
        <svncopy svnpath="${svnpath}" username="${svnuser}"
            password="${svnpass}" nocache="true"
            repositoryurl="svn://localhost/phing-the-things/trunk/"
            todir="svn://localhost/phing-the-things/tags/${version}" />
    </target>
    <target name="tag-version-no-file">
        <exec executable="git" outputProperty="latest-version">
            <arg line="tag | sort -t. -k 1,1n -k 2,2n -k 3,3n | tail -1" />
        </exec>
        <echo file="v.txt">${latest-version}</echo>
        <version releasetype="${release}" file="v.txt" property="version" />
        <delete file="v.txt" />
        <gittag annotate="true" name="${version}" repository="."
                    message="Tagged version ${version}" />
    </target>
    <property name="build-url"
            value="https://jenkins/job/phing/lastBuild/api/json?pretty=true" />
    <target name="require-green-build-check">
        <exec executable="curl" outputProperty="build-status">
            <arg line='--silent ${build-url} | grep result | cut -d" -f4' />
        </exec>
        <if>
            <not><equals arg1="${build-status}" arg2="SUCCESS" /></not>
            <then><fail message="Jenkins build is broken" /></then>
        </if>
    </target>
    <target name="deploy">
        <phingcall target="require-release" />
        <phingcall target="require-green-build-check" />
        <phingcall target="tag-version-no-file" />
    </target>
    <target name="build-config">
        <copy file="build/config/config.php.dist"
                tofile="build/config/config.php">
            <filterchain>
                <replacetokens>
                    <token key="DB-PASSWORD"
                            value="${db.password}" />
                </replacetokens>
            </filterchain>
        </copy>
    </target>
    
        <?php
        return array(
            'username' => 'appuser',
            'password' => '@DB-PASSWORD@',
        );
    
Prepare yourself - Deployment is coming
    <target name="prepare">
        <gitclone repository="git://gitserver/repos/phing-the-things.git"
                targetPath="build" />
        <gitcheckout repository="build" branchname="${version}" quiet="true" />
        <delete dir="build/tests" />
        <delete file="build/build.xml" />
        <phingcall target="build-config" />
        <tar destfile="build-${version}.tar.bz2" basedir="build"
                includeemptydir="true" compression="bzip2" />
        <delete dir="build" />
    </target>
    <target name="deploy">
        <phingcall target="require-release" />
        <phingcall target="require-green-build-check" />
        <phingcall target="tag-version-no-file" />
        <phingcall target="prepare" />
    </target>
    <target name="upload">
        <exec executable="scp" checkreturn="true">
            <arg value="build-${version}.tar.bz2" />
            <arg value="${server}:/var/www/" />
        </exec>
        <exec executable="ssh" checkreturn="true" passthru="true">
            <arg value="${server}" />
            <arg value="cd /var/www ; tar -xjf build-${version}.tar.bz2" />
        </exec>
    </target>
    <target name="deploy">
        <phingcall target="require-release" />
        <phingcall target="require-green-build-check" />
        <phingcall target="tag-version-no-file" />
        <phingcall target="prepare" />
        <phingcall target="upload" />
    </target>
    <target name="go-live" depends="require-version">
        <exec executable="ssh" checkreturn="true" passthru="true">
            <arg value="${server}" />
            <arg value="cd /var/www; ln -sf build-${version} app" />
        </exec>
    </target>
    <target name="deploy">
        <phingcall target="require-release" />
        <phingcall target="require-green-build-check" />
        <phingcall target="tag-version-no-file" />
        <phingcall target="prepare" />
        <phingcall target="upload" />
        <phingcall target="go-live" />
    </target>
sanity
check
Computer says no
phing-the-things$ phing go-live -Dversion=1.2.3
phing-the-things$ phing go-live -Dversion=1.2.3
Cat backpedalling
Omni Adams

/