Continuous integration for php

    This article was written by my good friend and former colleague fred, working in a team of programmers on a large and complex project that should work 24x7. If someone decides to invite him to the Habr - with pleasure I will send his email by habrpost. Suggestions and comments are welcome, and I undertake to convey the author's answers to the best of my ability.

    I had a long thought about launching a CI server for a working project. The base of unit tests is already quite impressive in size, and the number of people in the project has increased slightly. It would be possible to observe how coverage by code tests changes and coding standards are respected. And punish the guilty. Just kidding.
    Some time ago, the book Continuous Integration was read . Improving software quality and reducing riskand the article Quality Assurance Tools for PHP , which served as the starting point.

    The continuous integration server polls the project repository for changes at some intervals. If changes are found, then he
    1. generates documentation in phpdoc format
    2. checks code against coding standards
    3. runs tests
    4. builds metrics from the results of tests and code analysis, as well as the dynamics of changes in these metrics
    5. notifies everyone interested in case of successful or unsuccessful assembly

    CruiseControl was chosen as the integration server, along with a php plugin - http://phpundercontrol.org/ .

    Installing CruiseControl on a debian-like machine


    If you install CruiseControl on a different operating system, the steps are approximately the same: install java, unzip CruiseControl, make scripts for starting and stopping the server.
    To start CruiseControl itself, we need to install a Java machine:

    sudo apt-get install sun-java6-bin

    and write it in the environment variables:

    export JAVA_HOME = / usr / lib / jvm / java-6-sun

    First, create a user in the system from which CruiseControl will be launched:

    sudo adduser cruisecontrol

    Unfortunately, I did not find any fresh .deb packages with CruiseControl, but I haven’t gotten my hands on it yet, so we download the latest version and unpack it into the directory as desired:

    s.galkin@java-galkin: / opt $ sudo wget http://sourceforge.net/projects/cruisecontrol/files/CruiseControl/2.8.2/cruisecontrol-bin-2.8.2.zip/download
    s.galkin@java-galkin: / opt $ sudo unzip cruisecontrol-bin-2.8.2.zip
    s.galkin@java-galkin: / opt $ sudo mv cruisecontrol-bin-2.8.2 cruisecontrol

    and make the owner of our user directory:

    s.galkin@java-galkin: / opt $ sudo chown cruisecontrol / opt / cruisecontrol -R

    We take the shell script from the installation guide for CruiseControl on unix. and save it to the file /etc/init.d/cruisecontrol.
    Now you can run CC and verify that it works:

    s.galkin@java-galkin: / opt $ sudo /etc/init.d/cruisecontrol start

    The web interface should be available at http: // yourhostname: 8080 / You can
    stop the server accordingly:

    s.galkin@java-galkin: / opt $ sudo /etc/init.d/cruisecontrol stop

    We proceed to install the php part.
    You probably already have xdebug and pear, but if not:

    sudo apt-get install php5-xdebug
    sudo apt-cache search php pear

    If you have a lot of code and tests, you should increase the amount of memory allocated to the php process:

    max_execution_time = 0
    memory_limit = 512M

    Install php packages


    Now install the packages for documentation, testing, and code evaluation and phpUnderControl itself:

    pear install PhpDocumentor
    pear install PHP_CodeSniffer
    pear channel-discover pear.phpunit.de
    pear install phpunit / PHPUnit
    pear channel-discover components.ez.no
    pear install --alldeps phpunit / phpUnderControl-beta

    If you put everything on a separate machine, then do not forget to put all the libraries on which your project depends. At the same time, you can verify that phpunit, phpcs, phpdoc are executed with the parameter sets specified in build.xml.
    We make phpUnderControl a CruiseControl plugin, specifying as an argument the directory where the latter is installed:

    phpuc install / opt / cruisecontrol

    Project setup


    Open the config.xml configuration file located in the root directory of CruiseControl and replace it with the following:

      
      
     
      
      
     
      
      
      
      
      
      
      
     
      
     
      
        
          
        

     
        
          
        

     
        
          
        

     
        
          
            
            
            
            
            
          
        
     
        
          
        
     
        
          
          
          
          
        

      

    I moved all the paths to files and directories to variables at the very top of the configuration file, so that if necessary it was easy to fix them in one place.
    As a collector, I used ant (it is explicitly specified in config.xml in the / cruisecontrol / project / schedule node ), which is a little familiar to me. If your project already uses phing (which is more logical for php projects than ant), then CruiseControl supports it perfectly.
    In the / cruisecontrol / project / publishers node, in addition to processing test results and metrics, you can also send notifications to interested parties via mail / gill in case of unsuccessful builds (possibly successful ones).
    A detailed description of the configuration file can be found at CruiseControl Configuration Reference
    We pass to the project assembly scenario itself.

      
        
        
      
     
      
        
                   -o HTML: frames: DOM / earthli
            -ti '$ {ant.project.name} documentation'
            -q
            -t $ {project.api.dir}
            -d $ {project.code.dir}
          "/>
        
      
     
      
        
                  --report = checkstyle
            --standard = PEAR
            $ {project.code.dir}
          "/>
        
      
     
      
        
                   --log-xml $ {project.logs.dir} /phpunit.xml
            --log-pmd $ {project.logs.dir} /phpunit.pmd.xml
            --log-metrics $ {project.logs.dir} / phpunit.metrics.xml
            --coverage-xml $ {project.logs.dir} /phpunit.coverage.xml
            --coverage-html $ {project.coverage.dir}
            phpucAllTests $ {project.code.dir} / utests / AllTests .php
          "/>
      
      
     
      

    All path variables were passed from config.xml

        
        
        
        
        

    I decided to immediately put build.xml in the repository so that it would be easier to update in the future.
    Do not forget to correctly specify the path to it from config.xml (buildfile attribute in the / cruisecontrol / project / schedule / ant node )
    Now we upload your project to the / opt / cruisecontrol / projects / yourProjectName / source folder from the repository and run CruiseControl. All!

    Existing problems


    If there is a warning / notice, Codesniffer does not suppress them and the result is an invalid xml file that CruiseControl cannot read. In general, for any incomprehensible behavior, you can see the log /opt/cruisecontrol/cruisecontrol.sh

    Total


    As a result of the continuous integration server, we get the following advantages:
    • all developers are notified in a timely manner of a failed build
    • dynamics of changes in the number of tests
    • dynamics of changes in the percentage of code covered by tests
    • analysis of test coverage for specific classes
    • violation of coding standards
    • up-to-date documentation on internal api
    • static code analysis: too long methods, too complicated conditional logic, ...

    useful links


    1. The CruiseControl Best Practices Series
    2. Quality Assurance Tools for PHP
    3. RunningCruiseControlFromUnixInit
    4. Setting up phpUnderControl
    5. phpUnderControl
    6. CruiseControl Configuration Reference
    7. Running CodeSniffer with coding standards in a non-standard directory

    Also popular now: