Jenkins CI On Windows-PHP工具在构建时未执行


Jenkins CI On Windows - PHP Tools Not Executed At Build

我最近在本地Windows7开发环境中安装了Jenkins。

我为本地Java和Ant安装配置了Jenkins,并建立了我的第一个项目。

我使用了来自http://jenkins-php.org/在build.xml中指定的构建中执行某些PHP工具(PHP CodeSniffer、PHP Doc等)。

Pear在安装PHP工具包之前已经正确配置,因此包的所有package.bat文件(在Pear目录中)都有正确的PHP bin路径。此外,还设置了一个Windows环境变量PHPIN,指向php-bin位置——php-bin路径也在path变量上。

Pear路径(包含所有PHP工具的安装)也包含在path变量中。

当我手动启动构建时,我会收到错误消息,它无法运行某些程序(-->PHP工具),尽管它们是正确安装的(通过Pear),并且可以通过命令提示符执行。。。

以下是错误输出:

Started by user anonymous
Updating file:///D://SVN/MyProjectRepository/trunk/public_html
At revision 38
[workspace] $ cmd.exe /C '"ant.bat -file build.xml && exit %%ERRORLEVEL%%"'
Buildfile: C:'Servers'Jenkins'jobs'MyProject'workspace'build.xml
clean:
   [delete] Deleting directory C:'Servers'Jenkins'jobs'MyProject'workspace'build'api
   [delete] Deleting directory C:'Servers'Jenkins'jobs'MyProject'workspace'build'code-browser
   [delete] Deleting directory C:'Servers'Jenkins'jobs'MyProject'workspace'build'coverage
   [delete] Deleting directory C:'Servers'Jenkins'jobs'MyProject'workspace'build'logs
   [delete] Deleting directory C:'Servers'Jenkins'jobs'MyProject'workspace'build'pdepend
    [mkdir] Created dir: C:'Servers'Jenkins'jobs'MyProject'workspace'build'api
    [mkdir] Created dir: C:'Servers'Jenkins'jobs'MyProject'workspace'build'code-browser
    [mkdir] Created dir: C:'Servers'Jenkins'jobs'MyProject'workspace'build'coverage
    [mkdir] Created dir: C:'Servers'Jenkins'jobs'MyProject'workspace'build'logs
    [mkdir] Created dir: C:'Servers'Jenkins'jobs'MyProject'workspace'build'pdepend
parallelTasks:
pdepend:
phpcpd:
phpdoc:
phpcs:
phploc:
BUILD FAILED
C:'Servers'Jenkins'jobs'MyProject'workspace'build.xml:29: 
The following error occurred while executing this line:
C:'Servers'Jenkins'jobs'MyProject'workspace'build.xml:42: Execute failed: java.io.IOException: Cannot run program "pdepend": CreateProcess error=2, The system cannot find the file specified
The following error occurred while executing this line:
C:'Servers'Jenkins'jobs'MyProject'workspace'build.xml:62: Execute failed: java.io.IOException: Cannot run program "phpcpd": CreateProcess error=2, The system cannot find the file specified
The following error occurred while executing this line:
C:'Servers'Jenkins'jobs'MyProject'workspace'build.xml:80: Execute failed: java.io.IOException: Cannot run program "phpcs": CreateProcess error=2, The system cannot find the file specified
The following error occurred while executing this line:
C:'Servers'Jenkins'jobs'MyProject'workspace'build.xml:93: Execute failed: java.io.IOException: Cannot run program "phpdoc": CreateProcess error=2, The system cannot find the file specified
The following error occurred while executing this line:
C:'Servers'Jenkins'jobs'MyProject'workspace'build.xml:72: Execute failed: java.io.IOException: Cannot run program "phploc": CreateProcess error=2, The system cannot find the file specified
Total time: 0 seconds
Build step 'Invoke Ant' marked build as failure
[CHECKSTYLE] Skipping publisher since build result is FAILURE
[PMD] Skipping publisher since build result is FAILURE
[DRY] Skipping publisher since build result is FAILURE
[htmlpublisher] Archiving HTML reports...
[htmlpublisher] Archiving at PROJECT level C:'Servers'Jenkins'jobs'MyProject'workspace'build/code-browser to C:'Servers'Jenkins'jobs'MyProject'htmlreports'Code_Browser
ERROR: Directory 'C:'Servers'Jenkins'jobs'MyProject'workspace'build/code-browser' exists but failed copying to 'C:'Servers'Jenkins'jobs'MyProject'htmlreports'Code_Browser'.
Publishing Javadoc
[JDepend] JDepend plugin is ready
[JDepend] Couldn't generate JDepend file at 'build/logs/jdepend.xml'java.io.FileNotFoundException: C:'Servers'Jenkins'jobs'MyProject'workspace'build'logs'jdepend.xml (The system cannot find the file specified)
Sending e-mails to: test@localhost
Finished: FAILURE

有人能告诉我正确的方向吗?问题出在哪里?

简单的答案是:在Windows上以一种既不破坏执行又不破坏结果的方式设置构建文件是非常痛苦的。这不是詹金斯的问题,也不是蚂蚁的问题。这是QA工具。如果你有任何机会将詹金斯转移到一个*nix,那么就这样做。

特别是,当运行PHP QA工具时,请确保使用cmd /c调用它们,例如

<target name="pdepend">
    <exec executable="cmd">
        <arg line="/c pdepend
            --jdepend-xml='${basedir}/build/logs/jdepend.xml'
            … additional options
            sourcefolder1,sourcefolder2
        " />
    </exec>
</target>

还要确保你在任何路径上都没有空格,因为它们会导致问题。你也不能可靠地使用~字符(就像在DOS路径中一样),各种PHP工具对目录分隔符以及是否将多个源文件夹作为逗号分隔值等都有自己的想法。

请随时向GitHub的各种工具所有者报告您遇到的任何错误,以便修复它们。此外,还可以考虑在Freenode IRC上访问#jenkins.php。

查找适用于我的构建文件配置示例:

<?xml version="1.0" encoding="utf-8" ?> 
<project name="foo" default="build" basedir=".">
<target name="clean">
    <!-- Clean up -->
    <delete dir="${basedir}/build" />
    <!-- Create build directories -->
    <mkdir dir="${basedir}/build/api" />
    <mkdir dir="${basedir}/build/code-browser" />
    <mkdir dir="${basedir}/build/coverage" />
    <mkdir dir="${basedir}/build/logs" />
    <mkdir dir="${basedir}/build/pdepend" />
</target>
<!-- Run unit tests and generate junit.xml and clover.xml -->
<target name="phpunit">
    <exec executable="cmd">
        <arg line="/c phpunit '${basedir}/test'" />
    </exec>
</target>
<!-- Run the pdepend, phpmd, phpcpd, phpcs, phpdoc and phploc tasks in parallel 
    using a maximum of 2 threads. -->
<target name="parallelTasks">
    <parallel threadCount="1">
        <sequential>
            <antcall target="pdepend" />
            <antcall target="phpmd" />
        </sequential>
        <antcall target="phpcpd" />
        <antcall target="phpcs" />
        <antcall target="phpdoc" />
        <antcall target="phploc" />
    </parallel>
</target>
<!-- Generate jdepend.xml and software metrics charts -->
<target name="pdepend">
    <exec executable="cmd">
        <arg line="/c pdepend
            --jdepend-xml='${basedir}/build/logs/jdepend.xml'
            --jdepend-chart='${basedir}/build/pdepend/dependencies.svg'
            --summary-xml='${basedir}/build/logs/jdepend-summary.xml'
            --overview-pyramid='${basedir}/build/pdepend/overview-pyramid.svg'
            --ignore='${basedir}'lib'Zend'*'
            application,lib
            " />
    </exec>
</target>
<!-- Generate pmd.xml -->
<target name="phpmd">
    <exec executable="cmd">
        <arg line="/c phpmd application,lib
          xml
          codesize,design,naming,unusedcode
          --reportfile '${basedir}/build/logs/pmd.xml'
          --exclude '${basedir}'lib'Zend'*'
          " />
    </exec>
</target>
<!-- Generate pmd-cpd.xml -->
<target name="phpcpd">
    <exec executable="cmd">
        <arg line="/c phpcpd
            --log-pmd '${basedir}/build/logs/pmd-cpd.xml'
            --exclude '${basedir}/lib/Zend'
            application lib" />
    </exec>
</target>
<!-- Generate phploc.csv -->
<target name="phploc">
    <exec executable="cmd">
        <arg line="/c phploc
            --log-csv '${basedir}/build/logs/phploc.csv'
            --exclude '${basedir}/lib/Zend'
            application lib" />
    </exec>
</target>
<!-- Generate checkstyle.xml -->
<target name="phpcs">
    <exec executable="cmd">
        <arg line="/c phpcs
            --report=checkstyle
            --report-file='${basedir}/build/logs/checkstyle.xml'
            --standard='${basedir}/docs/coding-standard/ruleset.xml'
            --ignore=*''lib''Zend''*
            -p
            application lib" />
    </exec>
</target>
<!-- Generate API documentation -->
<target name="phpdoc">
    <exec executable="cmd">
        <arg line="/c phpdoc
            --directory application lib
            --target    '${basedir}/build/api'
            --ignore    '${basedir}/lib/Zend/*'
           " />
    </exec>
</target>
<target name="phpcb">
    <exec executable="cmd">
        <arg line="/c phpcb
          --log    '${basedir}/build/logs'
          --output '${basedir}/build/code-browser'
          --ignore '${basedir}/lib/Zend'
          " />
    </exec>
</target>
<target name="build" depends="clean,parallelTasks,phpunit,phpcb" />
</project> 

我也遇到了同样的问题,想要在Linux和Windows上运行Jenkins构建,在四处寻找了一段时间后,发现了一个适用于两者的相关解决方案:http://www.jguru.com/forums/view.jsp?EID=1560053

使用条件脚本后缀附加到每个可执行脚本:

<condition property="script-suffix" value=".bat" else="">
  <os family="windows" />
</condition>

然后你的脚本调用看起来是这样的:

<exec executable="phpmd${script-suffix}">
...
</exec>

用于每个PHP工具的可执行文件。它没有那么漂亮,但对我有用。

所以我的build.xml是这样的。请注意,我已经更改了一些php模板行为,以匹配我的特定项目(删除、配置文件位置等),这对于规范来说是不必要的。

<?xml version="1.0" encoding="UTF-8"?>
<project name="Project" default="build" basedir=".">
 <!-- ... defined properties ... -->
 <condition property="script-suffix" value=".bat" else="">
   <os family="windows" />
 </condition>
 <target name="clean"
         description="Clean up and create artifact directories">
  <delete>
    <fileset dir="${basedir}/build/api" />
    <fileset dir="${basedir}/build/coverage"/>
    <fileset dir="${basedir}/build/logs"/>
    <fileset dir="${basedir}/build/pdepend"/>
  </delete>
  <delete dir="${basedir}/build/code-browser"/>
  <mkdir dir="${basedir}/build/code-browser"/>
 </target>
 <target name="phpunit"
         description="Run unit tests using PHPUnit and generates junit.xml and clover.xml">
  <exec executable="phpunit${script-suffix}" failonerror="true">
   <arg value="-c" />
   <arg path="${basedir}/build/phpunit.xml" />
   <arg value="-d" />
   <arg value="memory_limit=1024M" />
   <arg path="${source}" />
  </exec>
 </target>
 <target name="parallelTasks"
         description="Run the pdepend, phpmd, phpcpd, phpcs, phpdoc and phploc tasks in parallel using a maximum of 2 threads.">
  <parallel threadCount="2">
   <sequential>
    <antcall target="pdepend"/>
    <antcall target="phpmd"/>
   </sequential>
   <antcall target="phpcpd"/>
   <antcall target="phpcs"/>
   <antcall target="phpdoc"/>
   <antcall target="phploc"/>
  </parallel>
 </target>
 <target name="pdepend"
         description="Generate jdepend.xml and software metrics charts using PHP_Depend">
  <exec executable="pdepend${script-suffix}">
   <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="${source}" />
  </exec>
 </target>
 <target name="phpmd"
         description="Generate pmd.xml using PHPMD">
  <exec executable="phpmd${script-suffix}">
   <arg path="${source}" />
   <arg value="xml" />
   <arg value="${basedir}/build/phpmd.xml" />
   <arg value="--reportfile" />
   <arg value="${basedir}/build/logs/pmd.xml" />
  </exec>
 </target>
 <target name="phpcpd"
         description="Generate pmd-cpd.xml using PHPCPD">
  <exec executable="phpcpd${script-suffix}">
   <arg value="--log-pmd" />
   <arg value="${basedir}/build/logs/pmd-cpd.xml" />
   <arg path="${source}" />
  </exec>
 </target>
 <target name="phploc"
         description="Generate phploc.csv">
  <exec executable="phploc${script-suffix}">
   <arg value="--log-csv" />
   <arg value="${basedir}/build/logs/phploc.csv" />
   <arg path="${source}" />
  </exec>
 </target>
 <target name="phpcs"
         description="Generate checkstyle.xml using PHP_CodeSniffer">
  <exec executable="phpcs${script-suffix}">
   <arg value="--report=checkstyle" />
   <arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
   <arg value="--standard=${basedir}/build/phpcs.xml" />
   <arg path="${source}" />
  </exec>
 </target>
 <target name="phpdoc"
         description="Generate API documentation using PHPDocumentor">
  <exec executable="phpdoc${script-suffix}">
   <arg value="-c" />
   <arg path="${basedir}/build/phpdoc.ini" />
  </exec>
 </target>
 <target name="phpcb"
         description="Aggregate tool output with PHP_CodeBrowser">
  <exec executable="phpcb${script-suffix}">
   <arg value="--log" />
   <arg path="${basedir}/build/logs" />
   <arg value="--source" />
   <arg path="${source}" />
   <arg value="--output" />
   <arg path="${basedir}/build/code-browser" />
  </exec>
 </target>
 <target name="build" depends="clean,parallelTasks,phpunit,phpcb"/>
 <!-- ... other targets ... -->
</project>