{"id":8557,"date":"2013-01-17T09:22:49","date_gmt":"2013-01-17T09:22:49","guid":{"rendered":"https:\/\/blog.jetbrains.com\/webide\/?p=4777"},"modified":"2013-01-17T14:32:42","modified_gmt":"2013-01-17T14:32:42","slug":"continuous-integration-for-php-using-teamcity","status":"publish","type":"webide","link":"https:\/\/blog.jetbrains.com\/fr\/webide\/2013\/01\/continuous-integration-for-php-using-teamcity","title":{"rendered":"Continuous Integration for PHP using TeamCity"},"content":{"rendered":"<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-00-intro.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignleft size-medium wp-image-4778\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-00-intro-300x245.png\" alt=\"\" width=\"175\" height=\"139\" \/><\/a><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-01-login.png\"><\/a>If you have multiple team members, you should be doing Continuous Integration (CI). By building the desired output artifacts on a frequent basis and analyzing their quality using unit tests and code coverage, you will find that there are fewer integration problems in working on a software project.<\/p>\n<p>In this blog post, we\u2019ll be using the open-source PHP project <a href=\"https:\/\/github.com\/PHPOffice\/PHPExcel\" target=\"_blank\" rel=\"noopener\">PHPExcel<\/a> as a sample project to set up Continuous Integration using <a href=\"http:\/\/www.jetbrains.com\/teamcity\/\" target=\"_blank\" rel=\"noopener\">TeamCity<\/a>. This project features a large amount of code, PHPUnit tests and uses Phing to create build artifacts. We\u2019ll use TeamCity to get this process completely automated and ready for immediate feedback once the source code on GitHub changes.<\/p>\n<p><!--more--><\/p>\n<h2>Installing the TeamCity environment<\/h2>\n<p><a href=\"http:\/\/www.jetbrains.com\/teamcity\/download\/index.html\" target=\"_blank\" rel=\"noopener\">TeamCity can be downloaded and installed<\/a> on various platforms such as Windows, Mac OSX and Linux. The installer contains two applications: the TeamCity web interface which we will be using to set up our continuous integration process and a build agent, a small service that listens for build commands and can run the CI configuration. Every TeamCity setup can have one or more build agents on one or more machines.<\/p>\n<p>Since installing TeamCity on various platforms is a bit different, we\u2019ll not go into detail on the installation. We have an <a href=\"http:\/\/confluence.jetbrains.net\/display\/TCD7\/Installing+and+Configuring+the+TeamCity+Server\" target=\"_blank\" rel=\"noopener\">installation guide<\/a> available that can be used to get TeamCity up and running.<\/p>\n<p>Before setting up our CI process, we\u2019ll assume that you already have a PHP environment with <a href=\"http:\/\/www.pear.net\/\" target=\"_blank\" rel=\"noopener\">PEAR<\/a>, <a href=\"http:\/\/www.phpunit.de\/\" target=\"_blank\" rel=\"noopener\">PHPUnit<\/a> and <a href=\"http:\/\/www.phing.info\/\" target=\"_blank\" rel=\"noopener\">Phing<\/a> installed. If not, now is the time. You can find more info on installing TeamCity on Linux and\u00a0on configuring your PHP environment through <a href=\"http:\/\/kogentadono.com\/2012\/05\/11\/part-1-setting-up-teamcity-for-php-ci-installing-tc\/\" target=\"_blank\" rel=\"noopener\">this blog post<\/a>.<\/p>\n<p><a name=\"setup\"><\/a><\/p>\n<h2>Setting up the project<\/h2>\n<p>After installing TeamCity, log in via the web interface. The first thing you will see after logging in is the projects overview. This screen will show you the various projects you have configured in TeamCity and gives immediate feedback on the status of these projects.<\/p>\n<p style=\"text-align: center\"><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-01-login.png\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-01-login-1024x748.png\" alt=\"\" width=\"640\" height=\"467\" \/><\/a><\/p>\n<p>Since we\u2019re on a clean install, let\u2019s create a project. Under <em>Administration |\u00a0Projects<\/em>,\u00a0click the <em>Create project <\/em>button. The first thing we\u2019ll have to do is give the project a name and a description.<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-02-createproject.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4782\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-02-createproject-1024x748.png\" alt=\"\" width=\"640\" height=\"467\" \/><\/a><\/p>\n<p>The next thing to do is creating a build configuration. This can be anything meaningful to your team: a build configuration per branch (although it\u2019s better to use TeamCity\u2019s <a href=\"http:\/\/blogs.jetbrains.com\/teamcity\/2012\/08\/07\/teamcity-7-1-control-the-flow\/\" target=\"_blank\" rel=\"noopener\">feature branching<\/a>), a build configuration for code and a separate one for documentation, or a build configuration per release.<\/p>\n<p>We\u2019ll create a build configuration named \u201cMain\u201d. Every build will be named with a number. This can be anything you want but since PHPExcel is currently in the 1.7.6.x range, let\u2019s go with \u201c1.7.6.{0}\u201d. TeamCity will automatically increment the revision version for every build. The build counter starts at 1, so our first build will be versioned 1.7.6.1.<\/p>\n<p>PHPExcel\u2019s build script creates build artifacts under the \u201dbuild\/release\/*\u201d folder. TeamCity can grab these from the configured artifact paths and display them in the TeamCity web interface once the build is finished. Don\u2019t worry: we can configure artifact paths later.<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-03-buildconfig.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4783\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-03-buildconfig-1024x727.png\" alt=\"\" width=\"640\" height=\"454\" \/><\/a><\/p>\n<p>In the next step, we have to provide Version Control System (VCS) settings. TeamCity supports a variety of version control systems such as Git, Mercurial, CVS, Subversion and many more. We\u2019ll go with Git and configure TeamCity to fetch sources from <a href=\"https:\/\/github.com\/maartenba\/PHPExcel.git\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/maartenba\/PHPExcel.git<\/a>. Note that if required we could add a number of options to the VCS settings: which branch to clone, whether to include submodules, at what interval TeamCity should check for changes, and so on.<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-04-vcs.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4784\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-04-vcs-1024x727.png\" alt=\"\" width=\"640\" height=\"454\" \/><\/a><\/p>\n<p>After adding the version control we can start adding build steps. We\u2019ll start with&#8230;<\/p>\n<h2>Unit tests<\/h2>\n<p>As a first step in the build process we\u2019re creating, we want to make sure all tests are green. Whenever there is a failing unit test, we want to fail the entire build and not provide any build artifacts. TeamCity comes with a number of predefined build steps for Java and .NET, but since we\u2019re on PHP we\u2019ll have to select the <em>Command Line<\/em> build runner.<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-05-unittests.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4787\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-05-unittests-1024x727.png\" alt=\"\" width=\"640\" height=\"454\" \/><\/a><\/p>\n<p>Since we want to run unit tests, the custom script could read something like <em>phpunit -c phpunit.xml<\/em> to run the PHPUnit configuration that\u2019s in PHPExcel\u2019s source code. Since there are a lot of unit tests to be run, why not report test results to TeamCity real-time so that our team members can see what\u2019s happening? I\u2019ve created a wrapper around PHPUnit which uses <a href=\"http:\/\/confluence.jetbrains.net\/display\/TCD7\/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages\" target=\"_blank\" rel=\"noopener\">service messages<\/a> to report build results. You can <a href=\"https:\/\/github.com\/maartenba\/phpunit-runner-teamcity\" target=\"_blank\" rel=\"noopener\">download this wrapper here <\/a>and locate it somewhere on the build agent or\u00a0have the build agent download it from the above GitHub repository directly using a second VCS root. If you want to use standard PHPUnit, add an XML report processing\u00a0build feature which processes PHPUnit\u2019s JUnit compatible XML report. This can be done after storing the current build step.<\/p>\n<p>We can now run our build: click the <em>Run&#8230; <\/em>button to start a build, go to the project dashboard and watch in real time which unit tests are passing or failing.<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-06-firstbuild.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4788\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-06-firstbuild-1024x727.png\" alt=\"\" width=\"640\" height=\"454\" \/><\/a><\/p>\n<p>Congratulations on your first build for a PHP project using TeamCity! Now let\u2019s add some more build steps since just running unit tests is only the first step&#8230;<\/p>\n<h2>Build using Phing<\/h2>\n<p>Our next build step will be invoking <a href=\"http:\/\/www.phing.info\/\" target=\"_blank\" rel=\"noopener\">Phing<\/a>, a PHP project build system or build tool based on\u00a0<a href=\"http:\/\/ant.apache.org\/\" target=\"_blank\" rel=\"noopener\">\u200bApache Ant<\/a>. PHPExcel comes with a Phing build script which we\u2019ll invoke after all unit tests have passed. Find the <em>Build Steps<\/em> again by clicking the <em>Edit Configuration Settings <\/em>link at the top-right in this screen.<\/p>\n<p>Next, add a new <em>Command Line <\/em>build step. This time we\u2019ll invoke Phing\u2019s command-line tool and pass some parameters to it:<\/p>\n<pre>phing -f build\\build.xml -DpackageVersion=%system.build.number%\r\n    -DreleaseDate=CIbuild -DdocumentFormat=doc release-standard<\/pre>\n<p>PHPExcel has four build targets defined (<em>release-standard<\/em>,\u00a0<em>release-documentation<\/em>, <em>release-pear<\/em> and <em>release-phar<\/em>), all providing different build artifacts. The release-standard\u00a0target which we\u2019ve now specified at the command line is the default build for PHPExcel which generates a ZIP file containing all source code and <a href=\"http:\/\/phpdoc.org\/\" target=\"_blank\" rel=\"noopener\">phpDocumentor<\/a> output.<\/p>\n<p>We are also passing Phing the current build number from TeamCity using Phing\u2019s <em>-D<\/em> command line switches. The build script can use these to create the correct file names. TeamCity actually provides a lot of variables you can use, including source control details like revision number and so on.<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-07-phing.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4793\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-07-phing-1024x727.png\" alt=\"\" width=\"640\" height=\"454\" \/><\/a><\/p>\n<p>If you haven\u2019t configured the artifact paths while creating our build project, it\u2019s best to do so now (see \u201c<a href=\"#setup\">Setting up the project<\/a>\u201d). We want to make sure that the ZIP file generated in this build script is available from TeamCity\u2019s web interface.<\/p>\n<p>Try running another build. You\u2019ll now see that unit tests are being run and afterwards the Phing build script is being run. From the project dashboard, navigate to the build that\u2019s running and open the <em>Artifacts <\/em>tab. Once the entire build is completed, you will find the ZIP file generated by the Phing build script is now available for download. The best thing is that you can even <a href=\"http:\/\/confluence.jetbrains.net\/display\/TCD7\/Enabling+Guest+Login\" target=\"_blank\" rel=\"noopener\">configure guest access<\/a> to TeamCity so the users of your project can come and download continuous integration artifacts.<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-08-artifacts.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4796\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-08-artifacts-1024x727.png\" alt=\"\" width=\"640\" height=\"454\" \/><\/a><\/p>\n<p>Nice, isn\u2019t it? Let\u2019s see what else is possible. How about&#8230;<\/p>\n<h2>Code Coverage<\/h2>\n<p>The first build step we created was running unit tests using PHPUnit. The nice thing about PHPUnit is that it can provide code coverage information as well, nicely formatted as an HTML report. What\u2019s even nicer is that TeamCity can display HTML reports on a custom tab in the build results.<\/p>\n<p>Let\u2019s first make sure code coverage is enabled. Edit the first build step (running PHPUnit) and make sure it uses PHPExcel\u2019s <em>phpunit-cc.xml <\/em>configuration file for configuring PHPUnit. This configuration file which is specific to PHPExcel outputs its code coverage report in the <em> unitTests\/codeCoverage<\/em> folder. While it is possible to add all generated files to TeamCity as a build artifact, it\u2019s cleaner to ZIP that entire folder and make it available as one single file. We can have TeamCity create this ZIP file for us by using a special <a href=\"http:\/\/confluence.jetbrains.net\/display\/TCD7\/Configuring+General+Settings#ConfiguringGeneralSettings-artifactPaths\" target=\"_blank\" rel=\"noopener\">artifact path pattern<\/a>! Edit the build artifacts again and make sure the following two artifact paths are specified:<\/p>\n<pre>build\/release\/*%system.build.number%*\r\nunitTests\/codeCoverage =&gt; coverage.zip<\/pre>\n<p>That\u2019s right: we can make TeamCity create a ZIP archive from the <em>unitTests\/codeCoverage<\/em> path by simply using <em>=&gt;<\/em> and specifying a target artifact name.<\/p>\n<p>Next, navigate to <em>Administration <\/em>and edit the <em>PHPExcel &#8211; CI <\/em>project. Under <em>Report Tabs<\/em>, we can add a custom report tab and point it to a file in the ZIP file we\u2019re creating every build.<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-09-reporttab.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4797\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-09-reporttab-1024x746.png\" alt=\"\" width=\"640\" height=\"466\" \/><\/a><\/p>\n<p>Run the build again.\u00a0Once it completes, the <em>Artifacts <\/em>tab should contain the <em>coverage.zip<\/em> file we\u2019ve just created. Next to that, there should now be an additional tab <em>Code Coverage<\/em> available which displays code coverage results:<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-10-coverage.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4798\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-10-coverage-1024x746.png\" alt=\"\" width=\"640\" height=\"466\" \/><\/a><\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-11-coverage2.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4799\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-11-coverage2-1024x746.png\" alt=\"\" width=\"640\" height=\"466\" \/><\/a><\/p>\n<p>Using the same approach (zipping HTML files and adding a custom report tab), it\u2019s very easy to add additional build reporting and display results from PHP mess detector, <a href=\"http:\/\/www.icosaedro.it\/phplint\/\" target=\"_blank\" rel=\"noopener\">PHPLint<\/a> or even have a tab available which displays <a href=\"http:\/\/www.phpdoc.org\/\" target=\"_blank\" rel=\"noopener\">phpDocumentor<\/a> contents.<\/p>\n<h2>What else is there?<\/h2>\n<p>TeamCity is a very versatile product. In this post, we\u2019ve seen that while there is no PHP support out-of-the-box, it is very easy to configure Continuous Integration for PHP with it. Next to this flexibility, a number of additional reports are available. For example, build history is tracked and you can check what happened in previous builds:<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-12-history.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4802\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-12-history-1024x746.png\" alt=\"\" width=\"640\" height=\"466\" \/><\/a><\/p>\n<p>Another interesting tab is <em>Statistics<\/em>. This tab shows general build statistics such as success rate, build duration and test count in a graphical format.<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-13-statistics.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4803\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-13-statistics-1024x655.png\" alt=\"\" width=\"640\" height=\"409\" \/><\/a><\/p>\n<p>Another thing I like when reviewing build results is the possibility to dive into the changes that are included in a specific build. For example, we can get a global overview of all changes:<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-14-changelog.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4804\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-14-changelog-1024x655.png\" alt=\"\" width=\"640\" height=\"409\" \/><\/a><\/p>\n<p>Note that we can drill down in the changes and inspect in which build a specific change was included for the first time or diff\u00a0with a previous version:<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-15-integrateddiff.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-4805\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-15-integrateddiff-1024x655.png\" alt=\"\" width=\"640\" height=\"409\" \/><\/a><\/p>\n<p>When working with an environment based on the IntelliJ Platform, like PhpStorm or WebStorm, it\u2019s easy to link TeamCity with the IDE. After installing the <a href=\"http:\/\/confluence.jetbrains.net\/display\/TCD7\/IntelliJ+Platform+Plugin\" target=\"_blank\" rel=\"noopener\">TeamCity plugin into your IDE<\/a> you\u2019ll notice that there are some useful little things like opening a unit test in the IDE from within TeamCity:<\/p>\n<p><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-16-openinide.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-4806\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2013\/01\/webide-16-openinide.png\" alt=\"\" width=\"434\" height=\"277\" \/><\/a><\/p>\n<p>Feel free to experiment with <a href=\"http:\/\/www.jetbrains.com\/teamcity\/\" target=\"_blank\" rel=\"noopener\">TeamCity<\/a>: it\u2019s 100% free for up to 20 build configurations!<\/p>\n<p><em>Develop with pleasure!<\/em><br \/>\n<em>\u2013 JetBrains Web IDE Team<\/em><\/p>\n","protected":false},"author":118,"featured_media":0,"comment_status":"open","ping_status":"open","template":"","categories":[808,2347],"tags":[379,743,190,45,359,72,443],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/webide\/8557"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/webide"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/types\/webide"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/users\/118"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/comments?post=8557"}],"version-history":[{"count":0,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/webide\/8557\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media?parent=8557"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/categories?post=8557"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/tags?post=8557"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/cross-post-tag?post=8557"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}