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

xav*_*ard 79 git hudson jenkins

我如何告诉Jenkins/Hudson仅针对我的Git树中特定项目的更改触发构建?

小智 64

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

不幸的是,股票Git插件目前没有"包含区域"功能(1.15).但是,有人在GitHub上发布了一些补丁,它们可以在Jenkins和Hudson上运行,实现你想要的功能.

构建它是一项小工作,但它的工作方式与广告一样,并且非常有用,因为我的一个Git树有多个独立项目.

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

更新:Git插件(1.16)现在具有"包含"区域功能.

  • 1.1.16是包含功能的正确版本号.(没有1.16) (5认同)

per*_*tus 34

基本上,你需要两份工作.一个用于检查文件是否已更改,另一个用于执行实际构建:

工作#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
Run Code Online (Sandbox Code Playgroud)

工作#2

配置此作业以获取参数GIT_REVISION,以确保您正在构建第一个作业选择构建的修订版本.

参数化构建字符串参数 参数化构建Git结帐

  • 如果自上次构建以来发生了两次或更多次提交怎么办?我想你可能会错过src中的更改,因为你只是在检查HEAD提交. (5认同)

Ant*_*bev 7

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

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

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

when {
    anyOf {
        changeset "nginx/**"
        changeset "fluent-bit/**"
    }
}
steps {
    sh "make build-nginx"
    sh "make start-nginx"
}
Run Code Online (Sandbox Code Playgroud)


Fra*_*erZ 6

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

/*
 * 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
}
Run Code Online (Sandbox Code Playgroud)


Bob*_*Bob 5

对于Bitbucket 存储库用户(以及使用源代码控制管理主机的其他人,其 Webhook 负载似乎不指示文件更改)。

无论我做什么,Git 插件“包含区域”似乎都会失败,并且总是触发该作业。我的设置是 Jenkins 2.268,在 Docker 容器中运行,根据文件更改找到一种正确的方法来实现构建作业简直就是炼狱,但下面是一个。

所需的 Jenkins 插件:

  • 格罗维
  • Bitbucket(或者,如果您在另一个 SCM 主机上:一个可以触发该主机的 Webhooks 上的构建的插件)

创建一个名为“Switch”的新Freestyle作业:

  1. 源代码管理:指示您的 SCM 信息(确保“要构建的分支”是正确的。
  2. 构建触发器>将更改推送到 Bitbucket 时构建:选中
  3. 构建步骤>执行系统 ​​Groovy 脚本(不仅仅是执行 Groovy 脚本!),未选中“使用 Groovy 沙箱”

剧本:

import jenkins.*;
import jenkins.model.*;

// CONFIGURATION
// Links between changed file patterns and job names to build
def jobsByPattern = [
  "/my-project/": "my-project-job",
  "my-super-project/":"super-job",
]

// Listing changes files since last build
def changeLogSets = build.changeSets
def changedFiles = []
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]
       changedFiles.add(file.path)
    }
  }
}

// Listing ad hoc jobs to build
jobsToBuild = [:] // declare an empty map
for(entry in jobsByPattern ) {
  def pattern = entry.key
  println "Check pattern: $pattern"
  for (int i = 0; i < changedFiles.size(); i++) {
    def file = changedFiles[i]
    println "Check file: $file"
    if( file.contains( pattern ) ) {
      def jobName = entry.value
      jobsToBuild[ jobName ] = true
      break
    }
  }
}

// Building appropriate jobs
jobsToBuild.each{
  def jobName = it.key
  println "$jobName must be built!"
  def job = Jenkins.instance.getJob(jobName)
  def cause = new hudson.model.Cause.UpstreamCause(build)
  def causeAction = new hudson.model.CauseAction(cause)
  Jenkins.instance.queue.schedule(job, 0, causeAction)
}
Run Code Online (Sandbox Code Playgroud)

我相信此方法可以处理自上次构建以来的多次提交,因此它似乎满足了需求。欢迎任何增强建议。