我已经搭建了Jenkins,但我想知道当前构建与上一个构建之间添加/更改的文件有哪些。如果源代码树的某些部分发生更改,我想运行一些长时间运行的测试。
经过在互联网上的搜索,我没有找到Hudson/Jenkins具有此功能的提及,尽管建议使用SVN提交后钩子来实现它。也许这很简单,每个人都(除了我)知道如何做到这一点!
这种可能吗?
我是按照以下方式完成的。我不确定是否是正确的方式,但它似乎正在工作。您需要安装Jenkins Groovy插件并执行以下脚本。
import hudson.model.*;
import hudson.util.*;
import hudson.scm.*;
import hudson.plugins.accurev.*
def thr = Thread.currentThread();
def build = thr?.executable;
def changeSet= build.getChangeSet();
changeSet.getItems();
ChangeSet.getItems()方法可以获取到变更内容。由于我使用的是accurev,我使用了如下代码:List<AccurevTransaction> accurevTransList = changeSet.getItems();
在这里,如果文件在当前构建窗口内被多次提交,那么修改后的列表将包含重复的文件名。
echo $SVN_REVISION
svn_last_successful_build_revision=`curl $JOB_URL'lastSuccessfulBuild/api/json' | python -c 'import json,sys;obj=json.loads(sys.stdin.read());print obj["'"changeSet"'"]["'"revisions"'"][0]["'"revision"'"]'`
diff=`svn di -r$SVN_REVISION:$svn_last_successful_build_revision --summarize`
构建 shell
中运行,仅适用于 Subversion。 - jollychang如果您正在轮询更改并使用 SVN 更新,则 CI 服务器将向您显示更改列表。但是,您似乎希望根据修改的文件更改构建行为。我认为没有任何一种基于 Jenkins 的开箱即用的方法可以做到这一点。
提交后钩子是一个合理的想法。您可以使作业参数化,并让您的钩子脚本根据提交的更改设置参数值启动构建。我不确定这对您来说可能有多难。
但是,您可能需要考虑将其拆分为两个单独的作业-一个在每次提交时运行,另一个用于您不总是需要的长时间运行的测试。个人而言,我更喜欢保持作业行为在执行之间保持一致。否则,可追溯性会受到影响。
/usr/bin/wget --output-document "-" --timeout=2 \
https://ci.example.com/jenkins/job/JOBID/build?token=MYTOKEN
BUILD_URL
环境变量构建API的URL。URL最终看起来像这样:https://ci.example.com/jenkins/job/JOBID/BUILDID/api/json/
import os
import json
import urllib2
# Make the URL
build_url = os.environ['BUILD_URL']
api = build_url + 'api/json/'
# Call the Jenkins server and figured out what changed
f = urllib2.urlopen(api)
build = json.loads(f.read())
change_set = build['changeSet']
items = change_set['items']
touched = []
for item in items:
touched += item['affectedPaths']
final changeSet = build.getChangeSet()
final changeSetIterator = changeSet.iterator()
while (changeSetIterator.hasNext()) {
final gitChangeSet = changeSetIterator.next()
for (final path : gitChangeSet.getPaths()) {
println path.getPath()
}
}
使用Jenkins流水线(支持API插件2.2或更高版本),这个解决方案对我有用:
def changeLogSets = currentBuild.changeSets
for (int i = 0; i < changeLogSets.size(); i++) {
def entries = changeLogSets[i].items
for (int j = 0; j < entries.length; j++) {
def entry = entries[j]
def files = new ArrayList(entry.affectedFiles)
for (int k = 0; k < files.size(); k++) {
def file = files[k]
println file.path
}
}
}
通过Groovy:
<!-- CHANGE SET -->
<% changeSet = build.changeSet
if (changeSet != null) {
hadChanges = false %>
<h2>Changes</h2>
<ul>
<% changeSet.each { cs ->
hadChanges = true
aUser = cs.author %>
<li>Commit <b>${cs.revision}</b> by <b><%= aUser != null ? aUser.displayName : it.author.displayName %>:</b> (${cs.msg})
<ul>
<% cs.affectedFiles.each { %>
<li class="change-${it.editType.name}"><b>${it.editType.name}</b>: ${it.path} </li> <% } %> </ul> </li> <% }
if (!hadChanges) { %>
<li>No Changes !!</li>
<% } %> </ul> <% } %>
#!/bin/bash
set -e
job_name="whatever"
JOB_URL="http://myserver:8080/job/${job_name}/"
FILTER_PATH="path/to/folder/to/monitor"
python_func="import json, sys
obj = json.loads(sys.stdin.read())
ch_list = obj['changeSet']['items']
_list = [ j['affectedPaths'] for j in ch_list ]
for outer in _list:
for inner in outer:
print inner
"
_affected_files=`curl --silent ${JOB_URL}${BUILD_NUMBER}'/api/json' | python -c "$python_func"`
if [ -z "`echo \"$_affected_files\" | grep \"${FILTER_PATH}\"`" ]; then
echo "[INFO] no changes detected in ${FILTER_PATH}"
exit 0
else
echo "[INFO] changed files detected: "
for a_file in `echo "$_affected_files" | grep "${FILTER_PATH}"`; do
echo " $a_file"
done;
fi;
这与以前略有不同——我需要一个用于特定文件夹上Git的脚本……因此,我基于jollychang编写了一个检查脚本。
它可以直接添加到作业的执行shell脚本中。如果没有检测到文件,它将exit 0
,即SUCCESS
……这样你就可以始终在代码库提交时触发,但只有在感兴趣的文件夹中的文件更改时才构建。
但是……如果您想要按需构建(即单击“立即构建”)并使用自上次构建以来的更改,您需要将_affected_files
更改为:
_affected_files=`curl --silent $JOB_URL'lastSuccessfulBuild/api/json' | python -c "$python_func"`
我试图将这个添加到评论中,但是评论中的代码是不行
:
只是想要美化来自heroin
的答案中的代码:
def changedFiles = []
def changeLogSets = currentBuild.changeSets
for (entries in changeLogSets) {
for (entry in entries) {
for (file in entry.affectedFiles) {
echo "Found changed file: ${file.path}"
changedFiles += "${file.path}"
}
}
}
git
插件会返回空的changeSet
,例如:
thr
上使用了安全导航(?
)运算符,那么build
可能为null,然后在下一行的build.getChangeSet()
处会抛出空指针异常,这种情况是有可能发生的。 - solstice333