git 如何仅在特定文件集发生更改时触发构建
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5243593/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to trigger a build only if changes happen on particular set of files
提问by xavier.seignard
How do I tell Jenkins/Hudson to trigger a build only for changes on a particular project in my Git tree?
如何告诉 Jenkins/Hudson 仅针对 Git 树中特定项目的更改触发构建?
采纳答案by Aaron Kushner
The Git plugin has an option (excluded region) to use regexes to determine whether to skip building based on whether files in the commit match the excluded region regex.
Git 插件有一个选项(排除区域)使用正则表达式根据提交中的文件是否与排除区域正则表达式匹配来确定是否跳过构建。
Unfortunately, the stock Git plugin does not have a "included region" feature at this time (1.15). However, someone posted patches on GitHub that work on Jenkins and Hudson that implement the feature you want.
不幸的是,库存的 Git 插件此时 (1.15) 没有“包含区域”功能。但是,有人在 GitHub 上发布了补丁,这些补丁适用于 Jenkins 和 Hudson,实现了您想要的功能。
It is a little work to build, but it works as advertised and has been extremely useful since one of my Git trees has multiple independent projects.
构建它是一项小工作,但它可以像宣传的那样工作并且非常有用,因为我的一个 Git 树有多个独立的项目。
https://github.com/jenkinsci/git-plugin/pull/49
https://github.com/jenkinsci/git-plugin/pull/49
Update: The Git plugin (1.16) now has the 'included' region feature.
更新:Git 插件 (1.16) 现在具有“包含”区域功能。
回答by peritus
Basically, you need two jobs. One to check whether files changed and one to do the actual build:
基本上,你需要两份工作。一种用于检查文件是否已更改,另一种用于进行实际构建:
Job #1
工作 #1
This should be triggered on changes in your Git repository. It then tests whether the path you specify ("src" here) has changes and then uses Jenkins' CLIto trigger a second job.
这应该在您的 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
Job #2
工作 #2
Configure this job to take a parameter GIT_REVISION like so, to make sure you're building exactly the revision the first job chose to build.
将此作业配置为采用这样的参数 GIT_REVISION,以确保您正在构建第一个作业选择构建的版本。
回答by Anton Golubev
If you are using a declarative syntax of Jenkinsfileto describe your building pipeline, you can use changesetcondition to limit stage execution only to the case when specific files are changed. This is now a standard feature of Jenkinsand does not require any additional configruation/software.
如果您使用Jenkinsfile的声明性语法来描述您的构建管道,您可以使用变更集条件将阶段执行限制为仅在特定文件发生更改的情况下。这现在是Jenkins的标准功能,不需要任何额外的配置/软件。
stages {
stage('Nginx') {
when { changeset "nginx/*"}
steps {
sh "make build-nginx"
sh "make start-nginx"
}
}
}
You can combine multiple conditions using anyOf
or allOf
keywords for ORor ANDbehaviour accordingly:
您可以相应地使用OR或AND行为的关键字anyOf
或allOf
关键字组合多个条件:
when {
anyOf {
changeset "nginx/**"
changeset "fluent-bit/**"
}
}
steps {
sh "make build-nginx"
sh "make start-nginx"
}
回答by Goodbye StackExchange
While this doesn't affect single jobs, you can use this script to ignore certain steps if the latest commit did not contain any changes:
虽然这不会影响单个作业,但如果最新提交不包含任何更改,您可以使用此脚本忽略某些步骤:
/*
* 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
}
回答by Uri Cohen
If the logic for choosing the files is not trivial, I would trigger script execution on each change and then write a script to check if indeed a build is required, then triggering a build if it is.
如果选择文件的逻辑不是微不足道的,我会在每次更改时触发脚本执行,然后编写脚本来检查是否确实需要构建,如果需要则触发构建。
回答by hhony
I answered this question in another post:
我在另一篇文章中回答了这个问题:
How to get list of changed files since last build in Jenkins/Hudson
如何获取自上次在 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;
You can add the check directly to the top of the job's exec shell, and it will exit 0
if no changes are detected... Hence, you can always poll the top level for check-in's to trigger a build.
您可以将检查直接添加到作业的 exec shell 的顶部,exit 0
如果未检测到任何更改,它就会...因此,您始终可以轮询顶层以进行签入以触发构建。
回答by Tomas Bjerre
You can use Generic Webhook Trigger Pluginfor this.
您可以为此使用通用 Webhook 触发器插件。
With a variable like changed_files
and expression $.commits[*].['modified','added','removed'][*]
.
使用变量 likechanged_files
和 expression $.commits[*].['modified','added','removed'][*]
。
You can have a filter text like $changed_files
and filter regexp like "folder/subfolder/[^"]+?"
if folder/subfolder
is the folder that should trigger builds.
您可以使用过滤器文本$changed_files
和过滤正则表达式,例如"folder/subfolder/[^"]+?"
如果folder/subfolder
是应该触发构建的文件夹。
回答by user12513208
I wrote this script to skip or execute tests if there are changes:
如果有更改,我编写了这个脚本来跳过或执行测试:
#!/bin/bash
set -e -o pipefail -u
paths=()
while [ "" != "--" ]; do
paths+=( "" ); 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 "$@"
So you can do something like:
因此,您可以执行以下操作:
./scripts/git-run-if-changed.sh cmd vendor go.mod go.sum fixtures/ tools/ -- go test
./scripts/git-run-if-changed.sh cmd vendor go.mod go.sum fixtures/ tools/ -- go test