# jenkins 构建php_在Jenkins中准备和构建PHP项目

jenkins 构建php

In a previous article, we went through the installation of Jenkins and prepared everything to get started. We will continue in this article by actually preparing our project. If you have a Jenkins setup ready from before, no need to go through the previous part – you can follow along with this one quite nicely.

## 准备作曲家 (Prepare composer)

We are going to prepare our project first. We could use the project supplied by Sebastian Bergmann, but it’s rather a basic project and will run without problems in Jenkins. In this article, we will be using a different repository in which we will have to overcome some hurdles. We will be using a fork of Jumph as our basis.

First and foremost, we have to make sure that we have tools like PHPUnit and PHP-CodeSniffer available. We can do this in two different ways. Either we install the packages on our Jenkins server through Pear or Composer globally, or we define the dependencies in our composer.json file. I decided to go with the latter method, so we can easily control the version of these tools on our own local machine as well as on Jenkins. So we start by adding the following lines to the composer.json file and run composer update.

"require-dev": {
"squizlabs/php_codesniffer": "~1.5.*",
"phpmd/phpmd": "~2.1.*",
"sebastian/phpcpd": "~2.0.*",
"pdepend/pdepend": "~2.0.*",
"phploc/phploc": "~2.0.*",
"phpunit/phpunit": "~4.3.*",
"theseer/phpdox": "~0.7.*",
},

If you want to know more about what each package does, have a look at Bruno’s article about PHP QA tools.

## 准备蚂蚁 (Prepare Ant)

On our Jenkins server, we will be using Ant. So in case Ant is not yet installed on your server, make sure it is by running the following command.

sudo apt-get install ant

Ant helps you automate the software build process. You define tasks, called targets, in the configuration file. Ant will read this file and perform the appropriate action. You can define dependencies to indicate in which order Ant should perform these tasks. The configuration file is the so called build.xml file. We are going to add this to our project, so Ant can perform these tasks on our Jenkins server. We are going to use the template provided by Sebastian Bergmann which can be found here. We add this to the root of our project.

Ant可帮助您自动化软件构建过程。 您可以在配置文件中定义称为目标的任务。 Ant将读取此文件并执行适当的操作。 您可以定义依赖关系以指示Ant应该按哪些顺序执行这些任务。 配置文件是所谓的build.xml文件。 我们将把它添加到我们的项目中，以便Ant可以在Jenkins服务器上执行这些任务。 我们将使用Sebastian Bergmann提供的模板，可以在这里找到。 我们将此添加到项目的根目录中。

To run Ant, you can kick off ant build on the command line. This means that Ant will run the build target. If no parameter is given, Ant will run the target as indicated in the configuration as default, which in this case is also build.

Let’s take a closer look at the build target.

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

The target is empty, however, it depends on a lot of other targets. It will first run the prepare target and then continue with the lint target until every target has been run. Let’s have a look at the phploc-ci target for example.

<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}/src"/>
<arg path="${basedir}/tests"/> </exec> </target> This target is fairly easy to understand. You will notice it depends on the prepare target. Since that was already run by the build target, it won’t run again. Then we get the executable, which is phploc, which will be executed by Ant. You installed this earlier with Composer. Lastly, we will see the PHPLOC specific arguments. Ant will run the following command line input based on this target configuration. 这个目标相当容易理解。 您会注意到这取决于prepare目标。 由于已经由build目标运行，因此不会再运行。 然后，我们获得了可执行文件phploc ，它将由Ant执行。 您之前在Composer中安装了此软件。 最后，我们将看到特定于PHPLOC的参数。 Ant将基于此目标配置运行以下命令行输入。 phploc --count-tests --log-csv /build/logs/phploc.csv --log-xml /build/logs/phploc.xml /src /tests The ${toolsdir} and ${basedir} are 2 variables. Depending on how they are configured, they might have an effect on the overall command line output ${toolsdir}${basedir}是2个变量。 根据它们的配置方式，它们可能会对整体命令行输出产生影响 As indicated above, if you only wanted to trigger this target, you should run ant phploc-ci on the command line. 如上所述，如果只想触发此目标，则应在命令行上运行ant phploc-ci Notice that this PHPLOC command will output a phploc.csv file and a phploc.xml file. The plugins installed in Jenkins earlier will read these files and convert them to graphs, for example. In the next article we will dive deeper into this topic. 注意，此PHPLOC命令将输出phploc.csv文件和phploc.xml文件。 例如，早先在Jenkins中安装的插件将读取这些文件并将其转换为图形。 在下一篇文章中，我们将深入探讨该主题。 If you look through the whole build.xml file, you will notice that it’s depending on 3 other separate config files for certain tools; build/phpmd.xml, build/phpdox.xml and build/phpunit.xml. These configuration files are requested by the actual tools. To find out more, look at their respective docs. 如果浏览整个build.xml文件，您会发现它取决于某些工具的其他3个单独的配置文件。 build / phpmd.xmlbuild / phpdox.xmlbuild / phpunit.xml 。 这些配置文件是实际工具所要求的。 要了解更多信息，请查看各自的文档。 Note that phpunit.xml is heavily inspired by the original phpunit.xml.dist file from Symfony2 since we are dealing with a Symfony2 project. 请注意，由于我们正在处理Symfony2项目，因此phpunit.xml受到Symfony2原始phpunit.xml.dist文件的启发。 ### 更改build.xml文件 (Changing the build.xml file) So, are we done? Unfortunately, not yet. The build.xml file is very generic and not completely suited for our project. First we need to define where tools like PHPUnit can be found. Our composer installed these automatically in the bin directory in the root of our project. We need to change the toolsdir property to the correct value. 那么，我们完成了吗？ 不幸的是，还没有。 build.xml文件非常通用，并不完全适合我们的项目。 首先，我们需要定义在哪里可以找到PHPUnit之类的工具。 我们的作曲家会自动将它们安装在项目根目录下的bin目录中。 我们需要将toolsdir属性更改为正确的值。 <property name="toolsdir" value="bin/" /> We can also clean up several commands. The current build.xml file defines that we on one hand have a src directory and on the other hand a tests directory. Since Symfony2 includes tests in the src directory, we can remove all paths to the tests directory like this example. 我们还可以清理几个命令。 当前的build.xml文件定义我们一方面具有src目录，另一方面具有tests目录。 由于Symfony2在src目录中包含测试，因此可以像本例一样删除测试目录的所有路径。 <arg path="${basedir}/tests"/>

Although it’s not required, I prefer to keep everything as clean as possible so it matches our project correctly.

Lastly, the current configuration for PHPDox as indicated in the build.xml file while writing this article does not work with the latest version in my case. I changed the target like below, so it correctly reads our configuration file.

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

### 建立新目标 (Creating new targets)

Everything has been set up to make sure all our QA tools will run as expected. However, our project is just a bit more complicated. If you analyzed the repository, you will notice that dependencies are regulated by Composer and Bower. Since it’s a Symfony project, we will also need a default parameters.yml file. We need to deal with these requirements to be able to set up the project correctly on Jenkins.

Let’s start off with the parameters.yml file. We can work with the default content of parameters.yml.dist, so we are just going to copy that file. We start by creating a new target named copy-parameters which executes the cp command.

<target name="copy-parameters" description="Copy parameters.yml file">
<exec executable="cp" failonerror="true">
<arg path="app/config/parameters.yml.dist" />
<arg path="app/config/parameters.yml" />
</exec>
</target>

Next up are Composer and Bower. I decided to install these globally on the Jenkins server by executing the following commands.

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/bin/composer

sudo apt-get install nodejs
sudo apt-get install npm
sudo npm install -g bower
sudo ln -s /usr/bin/nodejs /usr/bin/node #This is needed on certain linux distro's.

[Ed: Note that if you’re running all this in a VM hosted on Windows, BowerPHP will be a much better option than Bower.]

[Ed：请注意，如果要在Windows托管的VM中运行所有这些功能， 那么BowerPHP将是比Bower更好的选择。]

Now lets create a target for Composer.

<target name="composer" description="Installing composer dependencies">
<exec executable="composer" failonerror="true">
<arg value="install" />
<arg value="--dev" />
<arg value="--prefer-dist" />
<arg value="--no-progress" />

<env key="SYMFONY_ENV" value="test"/>
</exec>
</target>

It’s important to set SYMFONY_ENV to test so symfony knows it has to clear its test cache directory.

Let’s continue with Bower.

<target name="bower" description="Installing bower dependencies">
<exec executable="bower" failonerror="true">
<arg value="install" />
</exec>
</target>

The final thing we need to do, is to make sure these targets are executed. So we change the build target and add the 3 newly created targets in the order we want to execute them.

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

## 吉特 (Git)

The last thing we need to do is to prepare our .gitignore file. If you ever want to run an Ant target on your local machine, your build directory will be filled with log files which you don’t want to commit to your repository. So we add the following lines to the .gitignore file.

# build
!build/phpmd.xml
!build/phpunit.xml
!build/phpdox.xml
build/*

Perhaps you got a little confused by all the changes we made. For your convenience, here is a direct link to the commit with all the changes we described above.

## 在詹金斯创建项目 (Create the project in Jenkins)

Since our project is located on Github, I suggest you install the Github plugin within Jenkins. If you are using your own git server, you can just install the regular Git plugin. If you are uncertain how to install a plugin, check the previous article.

When you return to the overview, you have to click new item in the left menu. As item name, we fill in Jumph. Next, we choose the option copy existing item and fill in php-template as the project to copy from.

We will immediately be taken to the configuration page of this project. First we uncheck Disable build so our build will be enabled on save. Within the Github project input field, we fill in the URL to the Github project.

The last thing we have to do is choose the source management. In our case, this is git. Next, you have to fill in the repository link. If you use the HTTPS link, you don’t have to provide any additional credentials. We can decide which branches should be build, but since we only have a master branch, we will leave it as it is.

The configuration is done – it’s so easy because we used a predefined template. If you scroll down, you will exactly see what the template configured for us. Don’t forget to save your configuration before continuing.

## 开始构建 (Start a build)

If you followed all the steps so far, you should now be able to start a build. You can start a build by clicking build now in the left side menu of a project. You will notice at the bottom left table that a build appears.

If you click on the build itself, you will get a new side menu with options for this particular build. Click on console output to see exactly what’s going on. In my case, the first build failed due to missing some PHP extensions.

The console output comes in very handy for finding out why your project is failing. In my case, I just had to run sudo apt-get install php5-curl php5-xsl php5-sqlite php5-xdebug to install some needed packages. It took me a couple of builds to figure out what was missing, but with the console output, it’s easy to figure out what is going wrong. In the end, this is what my build history looks like.

Red means the build has failed, where blue means the build was successful. A failure can mean something went wrong with the configuration as we saw before, but it could also mean that unit tests have failed. If you open up your build.xml file again, you will notice that some targets got an attribute named failonerror which is set to true. If for some reason, that target fails, Ant will automatically stop and will report the build as broken.

Perhaps you expected a green ball instead of a blue ball when a build succeeds. There is a plugin available to show green balls instead of blue ones.

## 结论 (Conclusion)

In this article, we worked our way to a successful build. We had to prepare our project and create a job within Jenkins. Finally we had to debug our first couple of builds since we forgot to install some libraries.

In the next part, we will take a look at all the results Jenkins gives back.

jenkins 构建php

08-31
12-13 1332

11-05 1438
08-04 1万+
09-11 353
11-06 2245
12-30 518
07-17 3312
10-06 1123