仅当特定文件集发生更改时如何触发构建


Answers:


65

Git插件有一个选项(排除的区域),可使用正则表达式根据提交中的文件是否与排除的区域正则表达式匹配来确定是否跳过构建。

不幸的是,股票Git插件目前不具有“包含区域”功能(1.15)。但是,有人在GitHub上发布了可在Jenkins和Hudson上运行的补丁,这些补丁实现了所需的功能。

构建起来需要花点功夫,但是却像广告中所说的那样工作,并且由于我的一棵Git树有多个独立项目而非常有用。

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

更新:Git插件(1.16)现在具有“包含”区域功能。


5
1.1.16是所包含功能的正确版本号。(没有1.16)
丹·卡特

我无法使其正常运行,我有一个包含多个模块的存储库(域,通用,api,desktop_app等),例如,我想触发一个desktop_app的构建,将“包含的区域”放入production_app / *,我尝试了几种组合,例如./desktop_app甚至是绝对路径。而且我总是有Ignored commit c6e2b1dca0d1885: No paths matched included region whitelist。有什么线索吗?此处有更多详细信息:stackoverflow.com/questions/47439042/…–
FranAguiar

38

基本上,您需要两项工作。一种检查文件是否更改,另一种进行实际构建:

工作#1

这应该在Git存储库中的更改时触发。然后,它将测试您指定的路径(此处为“ 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

像这样配置该作业以使用参数GIT_REVISION,以确保您正在精确构建第一个作业选择构建的修订版。

参数化的构建字符串参数 参数化的构建Git签出


6
如果自上次构建以来发生了两次或更多次提交怎么办?我认为您可能会错过src中的更改,因为您仅在检查HEAD提交。
亚当·蒙森,

@AdamMonsen对。但是您可以轻松地使上面的脚本适应您要测试的任何情况/条件,例如,不针对HEAD,而是针对上次脚本运行时的HEAD。
2011年

有些东西在失踪$? || exit 0...... test $? -eq 0 || exit 0也许?
安塔克

30

如果您使用的声明语法Jenkinsfile来描述你的建筑的管道,你可以使用变更时,特定的文件被更改条件限制阶段执行只的情况。现在,这是Jenkins的标准功能,不需要任何其他配置/软件。

stages {
    stage('Nginx') {
        when { changeset "nginx/*"}
        steps {
            sh "make build-nginx"
            sh "make start-nginx"
        }
    }
}

您可以相应地使用ORAND行为的anyOfallOf关键字组合多个条件:

when {
    anyOf {
        changeset "nginx/**"
        changeset "fluent-bit/**"
    }
}
steps {
    sh "make build-nginx"
    sh "make start-nginx"
}

1
请记住,在某些情况下它不起作用。有关更多详细信息,请参阅issues.jenkins-ci.org/browse/JENKINS-26354
tamerlaha

7

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

/*
 * 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
}

1
@Karl会在适合您的情况下随时修复代码。那就是我在应用此代码时遇到的一个问题(在构建失败时,如果绝对最新的提交也没有更改api/文件夹,则不会重试此提交。)如果可以解决此问题,我希望提出更改!
再见StackExchange

2

如果选择文件的逻辑不平凡,我将在每次更改时触发脚本执行,然后编写脚本以检查是否确实需要构建,然后触发构建。


1

您可以为此使用通用Webhook触发器插件

带有变量changed_files和表达式$.commits[*].['modified','added','removed'][*]

您可以有一个类似的过滤器文本$changed_files和类似regexp的过滤器,例如"folder/subfolder/[^"]+?"iffolder/subfolder是应该触发构建的文件夹。


我正在尝试这样做,但是我有点迷路了。如何将更改后的文件的路径发送到jenkins?你能再解释一下吗?将变量changed_files放在哪里?
苏阿德

您需要在使用的Git服务中配置一个Webhook。如果是GitHub上有一个例子在这里:github.com/jenkinsci/generic-webhook-trigger-plugin/blob/master/...
托马斯BJERRE

实际上,当我使用Bitbucket时,我意识到在bibucket的push事件的有效负载中,Changed_files条目不可用(参考:confluence.atlassian.com/bitbucket/…),因此我不确定该怎么做。我将依靠我认为的提交消息。谢谢
苏阿德

1

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

自Jenkins / Hudson上次构建以来,如何获取已更改文件的列表

#!/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如果未检测到任何更改,它就会......因此,您始终可以轮询顶层以进行检入以触发构建。


1

我编写了此脚本以跳过或执行测试(如果有更改):

#!/bin/bash

set -e -o pipefail -u

paths=()
while [ "$1" != "--" ]; do
    paths+=( "$1" ); shift
done
shift

if git diff --quiet --exit-code "${BASE_BRANCH:-origin/master}"..HEAD ${paths[@]}; then
    echo "No changes in ${paths[@]}, skipping $@..." 1>&2
    exit 0
fi
echo "Changes found in ${paths[@]}, running $@..." 1>&2

exec "$@"

因此,您可以执行以下操作:

./scripts/git-run-if-changed.sh cmd vendor go.mod go.sum fixtures/ tools/ -- go test

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.