只有在特定文件集发生更改时才能触发构build

我想知道如何告诉jenkins / hudson触发一个构build,只是为了改变我的git树上的特定项目?

git插件有一个选项(排除区域),使用正则expression式根据提交中的文件是否与排除区域正则expression式匹配来确定是否跳过构build。 不幸的是,股票git插件目前没有“包含区域”function(1.15)。 但是,有人在github上发布了一些补丁,这些补丁在Jenkins和Hudson上运行,可以实现您想要的function。

这是一个小小的工作来build立,但它的作品广告,并已经非常有用,因为我的一个混帐树有多个独立的项目。

https://github.com/jenkinsci/git-plugin/pull/49

编辑:git插件(1.16)现在具有“包含”区域function。

所以,基本上你需要两份工作。 一个检查文件是否改变,一个是做实际的构build:

工作#1

这应该引起您的git repositoritory的变化。 然后testing你指定的path(“src”在这里)是否有变化,然后使用Jenkins的CLI触发第二个工作。

export JENKINS_CLI="java -jar /var/run/jenkins/war/WEB-INF/jenkins-cli.jar" export JENKINS_URL=http://localhost:8080/ export GIT_REVISION=`git rev-parse HEAD` export STATUSFILE=$WORKSPACE/status_$BUILD_ID.txt # Figure out, whether "src" has changed in the last commit git diff-tree --name-only HEAD | grep src # Exit with success if it didn't $? || exit 0 # Trigger second job $JENKINS_CLI build job2 -p GIT_REVISION=$GIT_REVISION -s 

工作#2

configuration这个工作就像这样取一个参数GIT_REVISION,以确保你正在构build第一个工作select构build的版本。

参数化的构建字符串参数参数化编译git checkout

如果select文件的逻辑不是微不足道的,我会在每次更改时触发脚本执行,然后编写一个脚本来检查是否确实需要构build,如果是,则触发构build。

我在另一篇文章中回答了这个问题:

https://stackoverflow.com/a/39862273/4709299

 #!/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; 

您可以将检查直接添加到作业的exec shell顶部,如果没有检测到任何更改,它将会exit 0因此,您始终可以轮询检入的最高级别以触发构build。

虽然这不会影响单个作业,但如果最新的提交没有包含任何更改,则可以使用此脚本来忽略某些步骤:

 /* * Check a folder if changed in the latest commit. * Returns true if changed, or false if no changes. */ def checkFolderForDiffs(path) { try { // git diff will return 1 for changes (failure) which is caught in catch, or // 0 meaning no changes sh "git diff --quiet --exit-code HEAD~1..HEAD ${path}" return false } catch (err) { return true } } if ( checkFolderForDiffs('api/') ) { //API folder changed, run steps here }