iliyan-trifonov / jenkins-ci-php

Docker image with Jenkins CI and full PHP configuration and tools
https://jenkins.iliyan-trifonov.com/
MIT License
28 stars 14 forks source link

Stucking at PHPunit #2

Closed AaronJan closed 9 years ago

AaronJan commented 9 years ago

I'm using this image for a couple of days and had one problem that I really don't know why:

Jenkins always get stuck in PHPUnit "Generating code coverage report in PHPUnit XML format..." process.

On my real machine only take less than 2 minutes, but in docker it's taking forever, and cpu usage is 100%. The project is an official Laravel 4.3 example, created by composer create-project laravel/laravel --prefer-dist, and the build.xml, phpunit.xml is like this:

build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="name-of-project" default="build">
 <!-- By default, we assume all tools to be on the $PATH -->
 <property name="toolsdir" value=""/>

 <!-- Uncomment the following when the tools are in ${basedir}/vendor/bin -->
 <!-- <property name="toolsdir" value="${basedir}/vendor/bin/"/> -->

 <target name="build"
         depends="prepare,lint,phploc-ci,pdepend,phpmd-ci,phpcs-ci,phpcpd-ci,phpunit,phpdox"
         description=""/>

 <target name="build-parallel"
         depends="prepare,lint,tools-parallel,phpunit,phpdox"
         description=""/>

 <target name="tools-parallel" description="Run tools in parallel">
  <parallel threadCount="2">
   <sequential>
    <antcall target="pdepend"/>
    <antcall target="phpmd-ci"/>
   </sequential>
   <antcall target="phpcpd-ci"/>
   <antcall target="phpcs-ci"/>
   <antcall target="phploc-ci"/>
  </parallel>
 </target>

 <target name="clean"
         unless="clean.done"
         description="Cleanup build artifacts">
  <delete dir="${basedir}/build/api"/>
  <delete dir="${basedir}/build/coverage"/>
  <delete dir="${basedir}/build/logs"/>
  <delete dir="${basedir}/build/pdepend"/>
  <delete dir="${basedir}/build/phpdox"/>
  <property name="clean.done" value="true"/>
 </target>

 <target name="prepare"
         unless="prepare.done"
         depends="clean"
         description="Prepare for build">
  <mkdir dir="${basedir}/build/api"/>
  <mkdir dir="${basedir}/build/coverage"/>
  <mkdir dir="${basedir}/build/logs"/>
  <mkdir dir="${basedir}/build/pdepend"/>
  <mkdir dir="${basedir}/build/phpdox"/>
  <property name="prepare.done" value="true"/>
 </target>

 <target name="lint" description="Perform syntax check of sourcecode files">
  <apply executable="php" failonerror="true">
   <arg value="-l" />

   <fileset dir="${basedir}/app/controllers">
    <include name="**/*.php" />
    <modified />
   </fileset>

   <fileset dir="${basedir}/app/tests">
    <include name="**/*.php" />
    <modified />
   </fileset>
  </apply>
 </target>

 <target name="phploc"
         description="Measure project size using PHPLOC and print human readable output. Intended for usage on the command line.">
  <exec executable="${toolsdir}phploc">
   <arg value="--count-tests" />
   <arg path="${basedir}/app/controllers" />
   <arg path="${basedir}/app/tests" />
  </exec>
 </target>

 <target name="phploc-ci"
         depends="prepare"
         description="Measure project size using PHPLOC and log result in CSV and XML format. Intended for usage within a continuous integration environment.">
  <exec executable="${toolsdir}phploc">
   <arg value="--count-tests" />
   <arg value="--log-csv" />
   <arg path="${basedir}/build/logs/phploc.csv" />
   <arg value="--log-xml" />
   <arg path="${basedir}/build/logs/phploc.xml" />
   <arg path="${basedir}/app/controllers" />
   <arg path="${basedir}/app/tests" />
  </exec>
 </target>

 <target name="pdepend"
         depends="prepare"
         description="Calculate software metrics using PHP_Depend and log result in XML format. Intended for usage within a continuous integration environment.">
  <exec executable="${toolsdir}pdepend">
   <arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" />
   <arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" />
   <arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" />
   <arg path="${basedir}/app/controllers" />
  </exec>
 </target>

 <target name="phpmd"
         description="Perform project mess detection using PHPMD and print human readable output. Intended for usage on the command line before committing.">
  <exec executable="${toolsdir}phpmd">
   <arg path="${basedir}/app/controllers" />
   <arg value="text" />
   <arg path="${basedir}/build/phpmd.xml" />
  </exec>
 </target>

 <target name="phpmd-ci"
         depends="prepare"
         description="Perform project mess detection using PHPMD and log result in XML format. Intended for usage within a continuous integration environment.">
  <exec executable="${toolsdir}phpmd">
   <arg path="${basedir}/app/controllers" />
   <arg value="xml" />
   <arg path="${basedir}/build/phpmd.xml" />
   <arg value="--reportfile" />
   <arg path="${basedir}/build/logs/pmd.xml" />
  </exec>
 </target>

 <target name="phpcs"
         description="Find coding standard violations using PHP_CodeSniffer and print human readable output. Intended for usage on the command line before committing.">
  <exec executable="${toolsdir}phpcs">
   <arg value="--standard=PSR2" />
   <arg value="--extensions=php" />
   <arg value="--ignore=autoload.php" />
   <arg path="${basedir}/app/controllers" />
   <arg path="${basedir}/app/tests" />
  </exec>
 </target>

 <target name="phpcs-ci"
         depends="prepare"
         description="Find coding standard violations using PHP_CodeSniffer and log result in XML format. Intended for usage within a continuous integration environment.">
  <exec executable="${toolsdir}phpcs" output="/dev/null">
   <arg value="--report=checkstyle" />
   <arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
   <arg value="--standard=PSR2" />
   <arg value="--extensions=php" />
   <arg value="--ignore=autoload.php" />
   <arg path="${basedir}/app/controllers" />
  </exec>
 </target>

 <target name="phpcpd"
         description="Find duplicate code using PHPCPD and print human readable output. Intended for usage on the command line before committing.">
  <exec executable="${toolsdir}phpcpd">
   <arg path="${basedir}/app/controllers" />
  </exec>
 </target>

 <target name="phpcpd-ci"
         depends="prepare"
         description="Find duplicate code using PHPCPD and log result in XML format. Intended for usage within a continuous integration environment.">
  <exec executable="${toolsdir}phpcpd">
   <arg value="--log-pmd" />
   <arg path="${basedir}/build/logs/pmd-cpd.xml" />
   <arg path="${basedir}/app/controllers" />
  </exec>
 </target>

 <target name="phpunit"
         depends="prepare"
         description="Run unit tests with PHPUnit">
  <exec executable="${toolsdir}phpunit" failonerror="true">
   <arg value="--configuration"/>
   <arg path="${basedir}/build/phpunit.xml"/>
  </exec>
 </target>

 <target name="phpdox"
         depends="phploc-ci,phpcs-ci,phpmd-ci"
         description="Generate project documentation using phpDox">
  <exec executable="${toolsdir}phpdox" dir="${basedir}/build"/>
 </target>
</project>

phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="../bootstrap/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         strict="true"
         verbose="true"
>

    <logging>
        <log type="coverage-html" target="coverage"/>
        <log type="coverage-clover" target="logs/clover.xml"/>
        <log type="coverage-crap4j" target="logs/crap4j.xml"/>
        <log type="coverage-xml" target="logs/coverage"/>
        <log type="junit" target="logs/junit.xml" logIncompleteSkipped="false"/>
    </logging>

    <testsuites>
        <testsuite name="Application Test Suite">
            <directory suffix="Test.php">../app/tests/</directory>
            <exclude>../vendor</exclude>
        </testsuite>
    </testsuites>

    <filter>
    <blacklist>
        <directory suffix=".php">../vendor</directory>
    </blacklist>
    <whitelist addUncoveredFilesFromWhitelist="true">
      <directory suffix=".php">../src</directory>
      <exclude>
        <file>../vendor/autoload.php</file>
        <file>../bootstrap/autoload.php</file>
      </exclude>
    </whitelist>
  </filter>
</phpunit>

Is something wrong in my xml files?

iliyan-trifonov commented 9 years ago

I have successfully repeated the problem, got stuck at the same place at 100%. This one was corrected when I changed src to app dir in phpunit.xml's whitelist block.

However I will give all the steps I just made to make a successful build in Jenkins with a Laravel project. Check the final result here: http://jenkins.iliyan-trifonov.com/job/LaravelTestEmptyProject/ You will see I've made a couple of tests while looking at the errors in the console output to make the configuration compatible with this project.

I've used my Gitlab and put the files here: http://gitlab.iliyan-trifonov.com/laravel/test-empty-laravel-project/tree/master

There's one requirement to the Jenkins Docker image that I corrected in the new version/tag: 1.0.3: php5-mcrypt was needed.

First check if all the builds finished here https://registry.hub.docker.com/u/iliyan/jenkins-ci-php/builds_history/72106/ and then fetch the new image with: sudo docker pull iliyan/jenkins-ci-php:1.0.3. Remove the current Jenkins container: sudo docker stop jenkins && sudo docker rm jenkins. Run the new one: sudo docker run -d --name jenkins -p 127.0.0.1:8080:8080 iliyan/jenkins-ci-php:1.0.3. You should be ready now to add your project with the configuration changes explained below.

These are the steps:

Local:

mkdir test-laravel-empty-project cd test-laravel-empty-project composer create-project laravel/laravel~4 . Create ./build.xml from your code here Add vendors configuration in build.xml (check my test repo on Gitlab) Add build/ dir with phpcs.xml, phpdox.xml, phpmd.xml and phpunit.xml (check my test repo on Gitlab) I will be using phpunit config from build/phpunit.xml. Change src dir to app in whitelist block in build/phpunit.xml and in build/phpdox.xml (check my test repo on Gitlab) Change logs/coverage to coverage/xml in build/phpunit.xml (check my test repo on Gitlab) git init git remote add origin ssh://git@gitlab.iliyan-trifonov.com:52222/laravel/test-empty-laravel-project.git git add . git commit -m "initial commit" git push -u origin master

Jenkins:

New project: LaravelTestEmptyProject - copy from php-template Uncheck Freeze build Check Git VCS I've set repo url to: http://gitlab.iliyan-trifonov.com/laravel/test-empty-laravel-project.git Change index.xhtml to index.html in the Publish HTML reports section. This will fix the missing Api documentation link in the Jenkins' project dashboard. Save Build Now

Mcrypt PHP extension required. If you are not on the 1.0.3 image, install the extension manually:

docker exec -ti jenkins bash apt-get update && apt-get install php5-mcrypt exit

This will add the extension to the container which you may commit to your personal images. Otherwise fetch the updated 1.0.3 image.

Click Build Now in Jenkins and it should succeed.

I also got used to letting the build.xml update composer and all its required tools as well as the vendors dir which makes it independent from the current tools' versions inside the image. For this variant check my other build here: https://github.com/iliyan-trifonov/mvc-behat-phpunit/blob/master/build.xml

AaronJan commented 9 years ago

Thank you for your very detailed reply! Really helped me a lot! :smile:

I ran into the missing mcrypt problem too, but your image setting timezone to Europe/Sofia, so I just builded an new image base on yours to solving this two things.

I'm building a PHP development system all around Docker, thanks for your helping, now I can get the whole thing working.

I think your configure files could help a lot people like me, maybe you can find a way to use them.

Thank you again!

iliyan-trifonov commented 9 years ago

I am happy to help! :smile:

You also helped me by letting me think about how to test a Laravel app and with the time zone. :+1:

I am planning to introduce environment vars while running the container to change the timezone on the fly but I guess I was waiting for it to be required :) I will make it next time I update the project.