如何让 Jenkins 使用来自 COMPOSER_HOME/bin 的二进制文件?
How to get Jenkins working with binaries from COMPOSER_HOME/bin?
我正在做一个项目,想为它使用 Jenkins。配置应该通过一个简单的 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
) 工作完美运行:
控制台输出
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
但是 PHPDox 的执行失败了:
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 软件包中遇到了同样的问题,这些软件包已安装 globally 并从 COMPOSER_HOME/bin
使用(例如 PHP_Codesniffer)。
我试过用另一种方式定义命令(比如<exec executable="cmd"><arg line="/c phpdox ..." /></exec>
),但它也不起作用。
直接执行 build.xml
和 ant
是可行的。
Composer 的环境变量设置正确——我可以通过 CLI(CMD 或 GitBash/MinGW)调用这些工具。所以问题一定是由其他原因引起的。它可以是什么?
如何让 Jenkins 使用通过 Composer 全局安装的包?
Linux(在我的例子中 Ubuntu 14.04 服务器)
在 Jenkins 配置中设置环境变量(Manage Jenkins -> Configure System -> Global properties -> Environment variables
:name=PATH, value=$PATH:$COMPOSER_HOME/vendor/bin/
)解决了问题。
$ echo $COMPOSER_HOME
/usr/share/.composer
请注意,$COMPOSER_HOME
should/may 不能设置为 (root
) 用户(例如 /root/.composer
)的子文件夹,因为它可能导致 :
Execute failed: java.io.IOException: Cannot run program "phpcs": error=13, Permission denied
Windows(在我的例子中 Windows Server 2008 r2)
除了 Composer 路径的设置之外,还需要一些进一步的步骤 were/are:
首先我得到了错误
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>
但它不起作用,只会导致下一个错误:
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
这不是 Jenkins 问题,而是 Ant 问题。 Ant docu page for 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.
...
所以在我的例子中,工作目标规范如下所示:
<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>
从现在开始构建通过。但是 phpcs
:
仍然存在问题
phpcs:
[phpcs] 'php' is not recognized as an internal or external command,
[phpcs] operable program or batch file.
[phpcs] Result: 1
通过在 Jenkins (Manage Jenkins -> Configure System -> Global properties -> Environment variables
) 的 Path
环境变量中添加 PHP
即可轻松解决此问题:
就是这样。 :)
我正在做一个项目,想为它使用 Jenkins。配置应该通过一个简单的 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
) 工作完美运行:
控制台输出
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
但是 PHPDox 的执行失败了:
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 软件包中遇到了同样的问题,这些软件包已安装 globally 并从 COMPOSER_HOME/bin
使用(例如 PHP_Codesniffer)。
我试过用另一种方式定义命令(比如<exec executable="cmd"><arg line="/c phpdox ..." /></exec>
),但它也不起作用。
直接执行 build.xml
和 ant
是可行的。
Composer 的环境变量设置正确——我可以通过 CLI(CMD 或 GitBash/MinGW)调用这些工具。所以问题一定是由其他原因引起的。它可以是什么?
如何让 Jenkins 使用通过 Composer 全局安装的包?
Linux(在我的例子中 Ubuntu 14.04 服务器)
在 Jenkins 配置中设置环境变量(Manage Jenkins -> Configure System -> Global properties -> Environment variables
:name=PATH, value=$PATH:$COMPOSER_HOME/vendor/bin/
)解决了问题。
$ echo $COMPOSER_HOME
/usr/share/.composer
请注意,$COMPOSER_HOME
should/may 不能设置为 (root
) 用户(例如 /root/.composer
)的子文件夹,因为它可能导致
Execute failed: java.io.IOException: Cannot run program "phpcs": error=13, Permission denied
Windows(在我的例子中 Windows Server 2008 r2)
除了 Composer 路径的设置之外,还需要一些进一步的步骤 were/are:
首先我得到了错误
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>
但它不起作用,只会导致下一个错误:
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
这不是 Jenkins 问题,而是 Ant 问题。 Ant docu page for Exec
:
Windows Users
The
<exec>
task delegates toRuntime.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....
所以在我的例子中,工作目标规范如下所示:
<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>
从现在开始构建通过。但是 phpcs
:
phpcs:
[phpcs] 'php' is not recognized as an internal or external command,
[phpcs] operable program or batch file.
[phpcs] Result: 1
通过在 Jenkins (Manage Jenkins -> Configure System -> Global properties -> Environment variables
) 的 Path
环境变量中添加 PHP
即可轻松解决此问题:
就是这样。 :)