我正在开发一个项目,并希望使用Jenkins。该配置应由目标很少的简单build.xml对象完成:
build.xml
<?xml version="1.0" encoding="UTF-8"?> <project name="MyProject" default="full-build"> <property name="phpcs" value="phpcs"/> <property name="phpdox" value="phpdox"/> <target name="full-build" depends="lint, phpdox" description="Performs static analysis, runs the tests, and generates project documentation"/> <target name="lint" description="Perform syntax check of sourcecode files"> <apply executable="php" taskname="lint" failonerror="true"> <arg value="-l" /> <fileset dir="${basedir}/module/"> <include name="**/*.php" /> </fileset> <fileset dir="${basedir}/phpunit/tests"> <include name="**/*.php" /> </fileset> </apply> </target> <target name="phpdox" description="Generate project documentation using phpDox"> <exec executable="${phpdox}" dir="${basedir}/ci/phpdox" taskname="phpdox"/> </target> </project>
PHP Lint(php -l)工作可完美运行:
php -l
Console Output
Started by user anonymous Building in workspace D:\Data\myproject > git.exe rev-parse --is-inside-work-tree # timeout=10 Fetching changes from the remote Git repository > git.exe config remote.origin.url https://github.com/MyAccount/MyProject.git # timeout=10 Fetching upstream changes from https://github.com/MyAccount/MyProject.git > git.exe --version # timeout=10 using .gitcredentials to set credentials > git.exe config --local credential.username myusername # timeout=10 > git.exe config --local credential.helper store --file=\"C:\Windows\TEMP\git8298647783094567497.credentials\" # timeout=10 Setting http proxy: my.proxy.tld:8080 > git.exe -c core.askpass=true fetch --tags --progress https://github.com/MyAccount/MyProject.git +refs/heads/*:refs/remotes/origin/* > git.exe config --local --remove-section credential # timeout=10 > git.exe rev-parse "refs/remotes/origin/master^{commit}" # timeout=10 > git.exe rev-parse "refs/remotes/origin/origin/master^{commit}" # timeout=10 Checking out Revision 54af2180160f47d518c42f58f56cba175ca2ee39 (refs/remotes/origin/master) > git.exe config core.sparsecheckout # timeout=10 > git.exe checkout -f 54af2180160f47d518c42f58f56cba175ca2ee39 > git.exe rev-list 54af2180160f47d518c42f58f56cba175ca2ee39 # timeout=10 [myproject] $ cmd.exe /C '"ant.bat && exit %%ERRORLEVEL%%"' Buildfile: D:\Data\myproject\build.xml lint: [lint] No syntax errors detected in D:\Data\myproject\module\Application\Module.php ... [lint] No syntax errors detected in D:\Data\myproject\phpunit\tests\Application\DummyTest.php
But the executing of PHPDox is failing:
phpdox: BUILD FAILED D:\Data\myproject\build.xml:18: Execute failed: java.io.IOException: Cannot run program "phpdox" (in directory "D:\Data\myproject\ci\phpdox"): CreateProcess error=2, The system cannot find the file specified at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048) at java.lang.Runtime.exec(Runtime.java:620) at org.apache.tools.ant.taskdefs.launcher.Java13CommandLauncher.exec(Java13CommandLauncher.java:58) at org.apache.tools.ant.taskdefs.Execute.launch(Execute.java:428) at org.apache.tools.ant.taskdefs.Execute.execute(Execute.java:442) at org.apache.tools.ant.taskdefs.ExecTask.runExecute(ExecTask.java:629) at org.apache.tools.ant.taskdefs.ExecTask.runExec(ExecTask.java:670) at org.apache.tools.ant.taskdefs.ExecTask.execute(ExecTask.java:496) at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106) at org.apache.tools.ant.Task.perform(Task.java:348) at org.apache.tools.ant.Target.execute(Target.java:435) at org.apache.tools.ant.Target.performTasks(Target.java:456) at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1405) at org.apache.tools.ant.Project.executeTarget(Project.java:1376) at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41) at org.apache.tools.ant.Project.executeTargets(Project.java:1260) at org.apache.tools.ant.Main.runBuild(Main.java:853) at org.apache.tools.ant.Main.startAnt(Main.java:235) at org.apache.tools.ant.launch.Launcher.run(Launcher.java:285) at org.apache.tools.ant.launch.Launcher.main(Launcher.java:112) Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified at java.lang.ProcessImpl.create(Native Method) at java.lang.ProcessImpl.<init>(ProcessImpl.java:386) at java.lang.ProcessImpl.start(ProcessImpl.java:137) at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029) ... 24 more Total time: 8 seconds Build step 'Invoke Ant' marked build as failure Finished: FAILURE
我在其他Composer软件包中也遇到了同样的问题,这些软件包已 全局安装并从中使用COMPOSER_HOME/bin(例如PHP_Codesniffer)。
Composer
COMPOSER_HOME/bin
PHP_Codesniffer
我试图以另一种方式(例如<exec executable="cmd"><arg line="/c phpdox ..." /></exec>)定义命令,但是它也无法 正常工作。
<exec executable="cmd"><arg line="/c phpdox ..." /></exec>
build.xmlwith ant作品的直接执行。
build.xmlwith ant
Composer的环境变量设置正确-我可以通过CLI 调用工具(CMD或GitBash / MinGW)。因此,问题一定是 由其他原因引起的。会是什么
如何使Jenkins处理通过Composer在全球安装的软件包?
Linux (in my case Ubuntu 14.04 Server))
设置在詹金斯配置环境变量(Manage Jenkins -> Configure System -> Global properties -> Environment variables: name=PATH, value=$PATH:$COMPOSER_HOME/vendor/bin/)解决了这个问题。
(Manage Jenkins -> Configure System -> Global properties -> Environment variables
name=PATH, value=$PATH:$COMPOSER_HOME/vendor/bin/)
$ echo $COMPOSER_HOME /usr/share/.composer
请注意,$COMPOSER_HOME不应将/不应将其设置为(root)用户(例如/root/.composer)的子文件夹,因为它可能导致权限 问题:
$COMPOSER_HOME
/root/.composer
Execute failed: java.io.IOException: Cannot run program “phpcs”: error=13, Permission denied
Windows (在我的情况下为Windows Server 2008 r2)
除了设置Composer路径外,还 需要一些其他步骤:
首先我得到了错误
Execute failed: java.io.IOException: Cannot run program “phpcs”: error=2, The system cannot find file specified
在我阅读的论坛上,目标需要获取可执行文件的路径, 如下所示:
<target name="phpcs"> <exec executable="C:\path\to\Composer\vendor\bin\phpcs" taskname="phpcs"> <arg value="--standard=PSR2" /> <arg value="--extensions=php" /> <arg value="--ignore=autoload.php" /> <arg path="${basedir}/module/" /> </exec> </target>
But it didn’t work and only causes the next error:
D:\path\to\build.xml:34: Execute failed: java.io.IOException: Cannot run program “C:\path\to\Composer\vendor\bin\phpcs”: CreateProcess error=193, %1 is not a valid Win32 application
It’s not a Jenkins, but an Ant issue. The cause and the solution are described on the Ant docu page for Exec:
Exec
Windows Users The <exec> task delegates to Runtime.exec which in turn apparently calls ::CreateProcess. It is the latter Win32 function that defines the exact semantics of the call. In particular, if you do not put a file extension on the executable, only “.EXE” files are looked for, not “.COM”, “.CMD” or other file types listed in the environment variable PATHEXT. That is only used by the shell. Note that .bat files cannot in general by executed directly. One normally needs to execute the command shell executable cmd using the /c switch. …
Windows Users
The <exec> task delegates to Runtime.exec which in turn apparently calls ::CreateProcess. It is the latter Win32 function that defines the exact semantics of the call. In particular, if you do not put a file extension on the executable, only “.EXE” files are looked for, not “.COM”, “.CMD” or other file types listed in the environment variable PATHEXT. That is only used by the shell.
<exec>
Runtime.exec
Note that .bat files cannot in general by executed directly. One normally needs to execute the command shell executable cmd using the /c switch.
cmd
/c
…
So in my case the working target specification looks as follows:
<target name="phpcs"> <exec executable="cmd" taskname="phpcs"> <arg value="/c" /> <arg value="C:\path\to\Composer\vendor\bin\phpcs" /> <arg value="--standard=PSR2" /> <arg value="--extensions=php" /> <arg value="--ignore=autoload.php" /> <arg path="${basedir}/module/" /> </exec> </target>
From now the build was passing through. But there was still an issue with phpcs:
phpcs
phpcs: [phpcs] 'php' is not recognized as an internal or external command, [phpcs] operable program or batch file. [phpcs] Result: 1
This is easily fixed by adding PHP to the Path environment variable in Jenkins (Manage Jenkins -> Configure System -> Global properties -> Environment variables):
PHP
Path
Manage Jenkins -> Configure System -> Global properties -> Environment variables
That’s it. :)