?

Log in

No account? Create an account
fedora 蓝色小药丸

Learning Jenkins

从同事那里借到“Jenkins (the Definitive Guide)”一直没有看,这两天突发奇想地装上Jenkins试了试。安装确实很简单,启动了服务,然后试着建了一个什么都不做的空白项目,又建了一个Maven类型的项目,然后关联起来。觉得挺好玩的。

安装时遇到一个bug,按照网上的帖子,降级到某个版本才好。它的代码在 https://github.com/jenkinsci/jenkins/

然后就开始纠结怎么编译Jenkins,也是建了一个Maven类型的项目,还要装Git插件,然后把Github那个路径填进去。我的Git还是用msysgit那个版本,所以要手工指定一下路径,而JDK和Maven就让它自动安装了。编译的时候出了两个问题,首先是service是用machine account来跑的,所以user.name是空值,有一个build.version的目标需要用到这个,那么把service改成user account或者设定maven cmdline options都可以解决问题。另一个问题是某些代码里包含“…”字符,有乱码、报错,才发现java的file.encoding是GBK,也就是windows的"非Unicode程序的默认locale",这个需要设定全局的JAVA_TOOL_OPTIONS。以上都是从SO或者博客上搜到的帖子。

出问题时显示的信息与实际的问题相差很远。像user.name为空,它的提示是"regex-property" Illegal group reference,正巧regex也有group一说,那段配置文件里也确实有类似group的括号。而file.encoding的问题,提示信息则是“Failed to execute goal", "unexpected token: https"”等等,这里的https本来是字符串的内容,但是字符串的引号已经跟“…”连在一起了。

编译失败了许多次。每次编译大约是五到十分钟,如果可以在命令行"edit and continue"就好了。最接近的一个命令大约是"mvn -am -rf"什么的?如果改了代码,想在jenkins里重新编译,一则是需要再看着网页,二则是它会自动把github/master签出来——不知道有什么办法。

中间还尝试了一下RedHat OpenShift的Jenkins,挺有意思的。网页还是显得挺粗糙的,如果删掉一个应用再加回来,页面要多刷新几次才不会显示404。只能创建一个Jenkins实例。不管创建什么应用,向导页面看起来都差不多,大概是后台的批处理工作不一样。自己对云服务还是不很明白,感觉就是更强大的cPanel?做应用的人需要适应各家的云服务,那应该会很难做吧。OpenShift Jenkins好像抢不到空闲进程似的,或许是哪儿没有设置好。

今天的最后一个问题是windows service的JENKINS_HOME,同样有SO的帖子讲了该怎么办(实际上用~/.jenkins最好不过,但是windows machine account有时会写到c:\.jenkins和c:\.m2??)。感觉现在所有事情都已经有人做过,所有的代码都有人写过,所有的问题都有人碰到过、有人解决过。过去看不出一个人有多么落后,现在很容易了。

edit: 在代码里看到了各种各样的技术。就像过去我们在代码里嵌xslt一样,现在可以嵌的东西也多了。一个文件引用几十个名字空间和类型,信息量太大。本来只要应付一个机器模型的,现在还要应付网络和数据库。真是麻烦。


从这里开始编译变得超慢,源码里的BUILDING.TXT说禁掉(-Dskip-test-harness)。
Running hudson.bugs.JnlpAccessWithSecuredHudsonTest
Tests run: 554, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 38.012 sec <<< FAILURE! - in CoreJellyTest
org.jvnet.hudson.test.JellyTestSuiteBuilder$JellyTestSuite(org.jvnet.hudson.test.junit.FailedTest)  Time elapsed: 0.006 sec  <<< ERROR!
java.io.IOException: Failed to clean up temp dirs
 at org.jvnet.hudson.test.TemporaryDirectoryAllocator.dispose(TemporaryDirectoryAllocator.java:86)
 at org.jvnet.hudson.test.TestEnvironment.dispose(TestEnvironment.java:81)
 at org.jvnet.hudson.test.HudsonTestCase.tearDown(HudsonTestCase.java:414)
 at org.jvnet.hudson.test.JellyTestSuiteBuilder$JellyTestSuite.tearDown(JellyTestSuiteBuilder.java:138)
 at org.jvnet.hudson.test.junit.GroupedTest.run(GroupedTest.java:53)
 at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84)
 at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)
 at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
 at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
 at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
 at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
 at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
Caused by: java.nio.file.FileSystemException: C:\OneTeam\Jenkins\jobs\Jenkins\workspace\test\target\hudson1256663408530103181test\secret.key: The process cannot access the file because it is being used by another process.

 at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
 at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
 at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
 at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269)
 at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
 at java.nio.file.Files.delete(Files.java:1077)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:606)
 at hudson.Util.deleteFile(Util.java:238)
 at hudson.Util.deleteRecursive(Util.java:301)
 at hudson.Util.deleteContentsRecursive(Util.java:203)
 at hudson.Util.deleteRecursive(Util.java:292)
 at hudson.FilePath$12.invoke(FilePath.java:1079)
 at hudson.FilePath$12.invoke(FilePath.java:1076)
 at hudson.FilePath.act(FilePath.java:914)
 at hudson.FilePath.act(FilePath.java:887)
 at hudson.FilePath.deleteRecursive(FilePath.java:1076)
 at org.jvnet.hudson.test.TemporaryDirectoryAllocator.dispose(TemporaryDirectoryAllocator.java:81)
 at org.jvnet.hudson.test.TestEnvironment.dispose(TestEnvironment.java:81)
 at org.jvnet.hudson.test.HudsonTestCase.tearDown(HudsonTestCase.java:414)
 at org.jvnet.hudson.test.JellyTestSuiteBuilder$JellyTestSuite.tearDown(JellyTestSuiteBuilder.java:138)
 at org.jvnet.hudson.test.junit.GroupedTest.run(GroupedTest.java:53)
 at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84)
 at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)
 at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
 at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
 at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
 at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
 at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)











edit: 还是没办法解决上面的问题。现在尝试 git plugin 的 "checkout to specific local branch"也出现问题,Git会输出颜色代码,可是/etc/gitconfig明明已经是禁掉颜色。然后还碰到多次找不到commit的情况,"Git Build Data"显示用到了一个错误的sha1。试用"merge before build"倒是很顺利。

正在读execute command一段,因为可以用来导出当前的环境信息。如果是运行cygwin bash,因为不是login shell所以不会执行/etc/profile,也不会设置PATH,在这个帖子里提到了。

读到了Enterprise Repository Manager一段。有Nexus的只读权限,不明白为什么仓库里那么乱。

在尝试用MSBuild编译我们的PresentationStudio.sln,设置起来挺简单的,连我们psbin脚本也可以跑。需要把domain用户的密码填进去,才能访问Git,不会违反公司政策吗?编译时有两个错误,一个是调用editbin时找不到路径(DevEnvDir未定义),还有就是一个xcopy找不到文件(路径里有空格?),感觉最好是把“Build Events”挪到别处去做。MSBuild插件如果能把各个project按照模块的方式列出来就好啦……

edit: 用msbuild编译三个.csproj而不是.sln,然后再用另外的job去跑.wixproj,把artifacts存到某个仓库里,这样的步骤应该更好一些。其中一个.csproj的本意是复制一些artifacts,方便DEBUG和packaging,如果用repository就可以也换掉。post build event脚本里用到$(SolutionDir)时需要换掉。

导出一个job原来只需要复制整个目录……真是没法再简单了。命令行还有导出导入xml。

看到一篇文章讲到其他的工具。看到另一篇文章讲到其他的CI服务器,尤其是CruiseControl.NET,我们也用了。现在看来,要想设计一个那样的结构,还是觉得困难。想要说出为什么Jenkins的结构更好,容易扩展,也受人欢迎,更觉得难了。直觉上是因为一个"build loop"的概念很难处理变动,而Jenkins一开始就选择了web服务器,可以定义API。可是多年前听说vmware的web服务器结构时,又觉得很不可思议,因为那么多的依赖关系、那么难设置?就没有想到过有一天可以这样。一直都在做客户端程序,一个dispatcher loop的概念很简单,可是以后还是最好不要做这个了。

edit: 看到一个很好的博客。本来是在看文档(1, 2, 3),想再了解得多一些。文章里提到几件事,串行化“Action”对象,把配置保存到仓库里,"Working memory",对"DRY"和master/slave execution的分析,都很有意思。现在更想了解多一些Jetty,Maven等等啦,虽然一旦上手,那种超长又无用的exception stack trace肯定会让人郁闷到死。另外,与页面表单相关的代码(Jelly),js模块,国际化的代码,都想看一看。

看"multi-configuration"的时候,代码里除了ANTLR (edit: 原来是eval groovy expression,对象是combination所以要产生很多的实例),还用到mockito。看起来执行顺序很怪异。有个帖子里说用到了code generation lib在.NET里也有类似的MoqFakeItEasy,应该试一下。。还看到了Castle Project。像这样跳来跳去地看,会看到无数新奇的东西的。
Tags:

Comments