简单的说就是 Hudson 的 Subversion 是根据时间戳来获取代码(只获取比Hudson 服务器当前时间早的代码)。如果Hudson 服务器和 Subversion 服务器上的时间不同步,尤其是Hudson 服务器慢于 Subversion 服务器就会产生问题(问题是某些在 Hudson 服务器上的时间之后的change 不能被同步下来)。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hudson中subversion HEAD check out 的问题及疑惑
近期发现一个问题,hudson执行任务时,经常不能获取到最新的代码,从而导致出现各种问题。
日常开发中的典型例子:发现一个bug,修改代码,本地测试通过,提交代码到subversion,手工激活hudson构建,原本期望hudson获取到刚刚提交的代码并测试/打包/发布。结果事与愿违,测试的结果发现刚刚做出的修改似乎没有生效。正费解之时,再执行一次hudson构建,又成功了...
经历过几次上述蹊跷遭遇之后,发现这个问题不是偶然。之后检查hudson的日志,发现问题的发现在最开始update / check out subversion代码时,明明已经提交的代码,hudson做update / check out时,居然没有update / check out下来!显示的subversion版本号也和subversion上实际的最新版本不一致,hudson总是要小一些,换言之,hudson update / check out的代码要比当前最新代码老一些。
google一番,发现这个问题之前就有人遭遇过,hudson上甚至已经有了好几个关于这个问题的bug,比如 http://issues.hudson-ci.org/browse/HUDSON-1241 "force using HEAD SVN version for build"。问题的根源在于hudson 获取subversion代码的方式,hudson是通过时间戳的方式来获取代码,而不是我们一般认为的"最新代码"即"HEAD"。这种方式通常没有问题,因为获取当前时间戳,然后要求update / checkout这个时间戳前的代码,理论上也是可以拿到最新代码的。
但是,如果hudson所在的服务器和subversion服务器时间不一致,这个机制就会出现问题:
我们假设subversion服务器的时间是准确的,再假设当时时间是15:10分,开发人员A提交代码,subversion上当前这个最新提交的代码时间戳为15:10:00。然后开发人员A手工激活hudson进行构建。hudson在15:10:20时开始check out代码。如果hudson时间无误,则hudson会发出请求说要求获取时间戳在15:10:20之前的代码,这样这个实际提交时间为15:10:00的新代码就可以如期的被check out。但是如果hudson的时钟有误,由于某些原因导致时钟偏慢2分钟,即在hudson上,"当前时间"为"15:08:20",则hudson获取代码的请求为:获取时间戳为15:08:20之前的代码,此时时间戳为15:10:00的新代码就无法checkout。
几分钟之后,疑惑的开发人员A再次激活hudson再次构建,假设此时时间时间是15:15:00,hudson慢两分钟为15:13:00。此时hudson发出请求: 获取时间戳为15:13:00之前的代码, 因此实际提交时间为15:10:00的新代码可以正常checkout,问题又在不知不觉被回避了。
总结说,hudson 获取代码的机制不是我们直觉中的获取最新代码(即subversion中HEAD checkout),而是基于时间戳。由于这个方式通常如HEAD般工作,因此我们总是容易误解为是获取最新代码。当hudson的时钟晚于subversion时,悲剧就出现了。
对这个问题,有几点疑惑:
1. 不明白为什么hudson不采用最直接最简单最容易被人理解最不容易出误解的HEAD checkout,而要基于时间戳
2. 这个问题很早就发生了,上面提到的bug 08年就被人提出, "Created: 31/Jan/08 05:37 AM Updated: 01/Jul/10 11:06 AM",三年了类似的bug被多次提出,但是就是始终没有修复。
修复的方式很简单,就改一个类的一行代码
in Class: hudson.scm.SubversionSCM
line 377:
final SVNRevision revision = SVNRevision.create(timestamp);
replace to:
final SVNRevision revision = SVNRevision.HEAD;
hudson拒绝修复的理由是什么?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hudson中subversion HEAD check out 的问题及疑惑
近期发现一个问题,hudson执行任务时,经常不能获取到最新的代码,从而导致出现各种问题。
日常开发中的典型例子:发现一个bug,修改代码,本地测试通过,提交代码到subversion,手工激活hudson构建,原本期望hudson获取到刚刚提交的代码并测试/打包/发布。结果事与愿违,测试的结果发现刚刚做出的修改似乎没有生效。正费解之时,再执行一次hudson构建,又成功了...
经历过几次上述蹊跷遭遇之后,发现这个问题不是偶然。之后检查hudson的日志,发现问题的发现在最开始update / check out subversion代码时,明明已经提交的代码,hudson做update / check out时,居然没有update / check out下来!显示的subversion版本号也和subversion上实际的最新版本不一致,hudson总是要小一些,换言之,hudson update / check out的代码要比当前最新代码老一些。
google一番,发现这个问题之前就有人遭遇过,hudson上甚至已经有了好几个关于这个问题的bug,比如 http://issues.hudson-ci.org/browse/HUDSON-1241 "force using HEAD SVN version for build"。问题的根源在于hudson 获取subversion代码的方式,hudson是通过时间戳的方式来获取代码,而不是我们一般认为的"最新代码"即"HEAD"。这种方式通常没有问题,因为获取当前时间戳,然后要求update / checkout这个时间戳前的代码,理论上也是可以拿到最新代码的。
但是,如果hudson所在的服务器和subversion服务器时间不一致,这个机制就会出现问题:
我们假设subversion服务器的时间是准确的,再假设当时时间是15:10分,开发人员A提交代码,subversion上当前这个最新提交的代码时间戳为15:10:00。然后开发人员A手工激活hudson进行构建。hudson在15:10:20时开始check out代码。如果hudson时间无误,则hudson会发出请求说要求获取时间戳在15:10:20之前的代码,这样这个实际提交时间为15:10:00的新代码就可以如期的被check out。但是如果hudson的时钟有误,由于某些原因导致时钟偏慢2分钟,即在hudson上,"当前时间"为"15:08:20",则hudson获取代码的请求为:获取时间戳为15:08:20之前的代码,此时时间戳为15:10:00的新代码就无法checkout。
几分钟之后,疑惑的开发人员A再次激活hudson再次构建,假设此时时间时间是15:15:00,hudson慢两分钟为15:13:00。此时hudson发出请求: 获取时间戳为15:13:00之前的代码, 因此实际提交时间为15:10:00的新代码可以正常checkout,问题又在不知不觉被回避了。
总结说,hudson 获取代码的机制不是我们直觉中的获取最新代码(即subversion中HEAD checkout),而是基于时间戳。由于这个方式通常如HEAD般工作,因此我们总是容易误解为是获取最新代码。当hudson的时钟晚于subversion时,悲剧就出现了。
对这个问题,有几点疑惑:
1. 不明白为什么hudson不采用最直接最简单最容易被人理解最不容易出误解的HEAD checkout,而要基于时间戳
2. 这个问题很早就发生了,上面提到的bug 08年就被人提出, "Created: 31/Jan/08 05:37 AM Updated: 01/Jul/10 11:06 AM",三年了类似的bug被多次提出,但是就是始终没有修复。
修复的方式很简单,就改一个类的一行代码
in Class: hudson.scm.SubversionSCM
line 377:
final SVNRevision revision = SVNRevision.create(timestamp);
replace to:
final SVNRevision revision = SVNRevision.HEAD;
hudson拒绝修复的理由是什么?