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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 10:18:21  来源:igfitidea点击:

How to trigger a build only if changes happen on particular set of files

githudsonjenkins

提问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,以确保您正在构建第一个作业选择构建的版本。

Parameterized build string parameterParameterized build Git checkout

参数化构建字符串参数参数化构建 Git checkout

回答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 anyOfor allOfkeywords for ORor ANDbehaviour accordingly:

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

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 0if 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_filesand expression $.commits[*].['modified','added','removed'][*].

使用变量 likechanged_files和 expression $.commits[*].['modified','added','removed'][*]

You can have a filter text like $changed_filesand filter regexp like "folder/subfolder/[^"]+?"if folder/subfolderis 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