28

Jenkins 有一个可用于自由式构建作业的 $CAUSE 变量。

如何在工作流程中访问此内容或类似内容?

我的团队在现有临时构建的电子邮件输出中使用它。我们希望在新的基于工作流的工作中继续这样做。

4

11 回答 11

26

看起来工作流构建没有注入这个变量。但是,您可以使用hudson.model.Run.getCause()hudson.model.Run.getCauses()方法从currentBuild.rawBuild对象中检索所需的信息。

例子:

工作流脚本:

println "CAUSE ${currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause).properties}"

此输出的结果:

Running: Print Message
CAUSE [userName:John Smith, userId:jsmith, class:class hudson.model.Cause$UserIdCause, shortDescription:Started by user John Smith]

其他原因子类型可以在javadoc中找到。

还有一个很好的get-build-cause示例,它基于 jenkins Pipeline Examples存储库中的这个答案。

于 2015-11-27T18:07:14.650 回答
15

截至 2018 年初,随着JENKINS-31576的关闭,这些信息似乎已经可用:

def manualTrigger = true
currentBuild.upstreamBuilds?.each { b ->
  echo "Upstream build: ${b.getFullDisplayName()}"
  manualTrigger = false
}
于 2018-04-23T12:54:19.907 回答
8

从 Jenkins 2.22 ( JENKINS-41272 ) 开始,您可以访问该currentBuild.getBuildCauses()方法以获取一系列构建原因。例如:

environment {
  CAUSE = "${currentBuild.getBuildCauses()[0].shortDescription}"
}

steps {
  echo "Build caused by ${env.CAUSE}"
}
于 2020-06-08T18:46:19.263 回答
6

我正在回复 Jazzschmidt 的回答,因为我没有足够的代表...... previousBuild 做错了,因为它获得了先前启动的相同类型的作业,而不是启动当前作业的作业。如果该工作最初是由某人发起的,那么这就是您将得到的人。否则,响应将为 NULL,这将导致尝试获取其 userId 的异常。

要获得“原始”原因,您必须使用UpstreamCause遍历原因。这就是我最终做的事情,尽管可能还有其他方法:

@NonCPS
def getCauser() {
  def build = currentBuild.rawBuild
  def upstreamCause
  while(upstreamCause = build.getCause(hudson.model.Cause$UpstreamCause)) {
    build = upstreamCause.upstreamRun
  }
  return build.getCause(hudson.model.Cause$UserIdCause).userId
}
于 2017-08-30T15:28:14.337 回答
6

如果构建是由 user 、 SCM 或 pull request 触发的,您可以使用以下命令来获取原因:

def SCMTriggerCause
def UserIdCause
def GitHubPRCause
def PRCause = currentBuild.rawBuild.getCause(org.jenkinsci.plugins.github.pullrequest.GitHubPRCause)
def SCMCause = currentBuild.rawBuild.getCause(hudson.triggers.SCMTrigger$SCMTriggerCause)
def UserCause = currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause)

if (PRCause) {
    println PRCause.getShortDescription()
} else if (SCMCause) {
    println SCMCause.getShortDescription()
} else if (UserCause) {
    println UserCause.getShortDescription()
}else {
   println "unknown cause"
}

注意:您必须在脚本部分中运行

归功于这个 github:https ://github.com/benwtr/jenkins_experiment/blob/master/Jenkinsfile

于 2018-06-07T16:52:21.637 回答
4

我们都喜欢单线,所以让我在这里分享一个:

env.STARTED_BY = currentBuild.getBuildCauses().iterator().next().userId ?: "SYSTEM"

为了打破它,在 2.22 管道插件发布之后,getBuildCauses添加了一个很好的方法来访问构建原因。

如果你像这样运行你的工作:

def causes = currentBuild.getBuildCauses()
causes.each {
    echo "$it"
}
echo "${causes.iterator().next().userId}"

你会看见:

[Pipeline] echo
[_class:hudson.model.Cause$UserIdCause, shortDescription:Started by user User Name (user.name), userId:user.name, userName:User Name (user.name)]
[Pipeline] echo
user.name

如果它是由 cron 启动的,那么您将看到:

[Pipeline] echo
[_class:hudson.triggers.TimerTrigger$TimerTriggerCause, shortDescription:Started by timer]
[Pipeline] echo
null
于 2020-01-24T09:56:55.867 回答
2

$BUILD_CAUSE 环境不适用于管道 currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause) ,如果构建是由 SCM 更改或计时器触发的,那么在多分支管道中甚至会失败。所以,我实施了以下解决方法..

    def manualTrigger = false
    node('master'){
       def causes = currentBuild.rawBuild.getCauses()
       for(cause in causes) {
          if(cause.properties.shortDescription =~ 'Started by user') {
             manualTrigger = true
             break
          }
      }
  }

我的工作流程的其余部分在另一个节点中

   node('nodefarm') {
       if(manualTrigger) {
         // do build stuff here
       } else {
         //build not triggered by user.
       }
   } 
于 2018-04-20T19:00:10.973 回答
2

如果构建是由上游构建触发的,您必须遍历currentBuild层次结构。

例如:

println getCauser(currentBuild).userId

@NonCPS
def getCauser(def build) {
    while(build.previousBuild) {
        build = build.previousBuild
    }

    return build.rawBuild.getCause(hudson.model.Cause$UserIdCause)
}

这将返回原始用户原因的用户 ID。

于 2017-08-09T13:37:36.323 回答
1

我猜您说的是在电子邮件分机插件中定义的宏。正在进行的工作是使该插件直接支持 Workflow。我不确定这个特定宏的状态。

于 2015-12-01T23:06:12.637 回答
0

所有的答案都涉及到正在运行的工作中。但是,您可以通过执行以下操作获取此帖子以查询历史记录:

 def job = hudson.model.Hudson.instance.getItem("test_job");
 def build = job.getBuild("8141")
 println(build.getCauses())

[job/run_tests/9532[job/master_pipeline/10073[job/GitBuildHook/9527[hudson.model.Cause$RemoteCause@3c1d9a68]]]]

在这种情况下,测试是由 git commit 触发的 3 个相互调用的作业引起的RemoteCause。因为我使用 python 来收集这个,我可以重新格式化字符串以将原因作为这样的列表返回

def get_build_cause(jenkins_session, job_name, build_number):
    Q =(  f'def job = hudson.model.Hudson.instance.getItem("{job_name}");\n'
        f'def build = job.getBuild("{build_number}")\n'
        'println(build.getCauses())'
    )
    
    causes = jenkins_session.run_script( Q ).strip().split('[')
    causes[-1] = causes[-1][:-(len(causes)-1)]
    return causes

有关 python api 的更多信息,请参阅https://python-jenkins.readthedocs.io/en/latest/api.html#jenkins.Jenkins.run_script

编辑:
这是原因对象的方法的 API 文档。如果你想以艰难的方式去做:-) https://javadoc.jenkins-ci.org/hudson/model/Cause.UpstreamCause.html

于 2021-10-01T19:54:15.597 回答
0

可以启动触发插件使用getCause方法吗?

当启动触发器插件触发构建时,以下命令返回 null:

currentBuild.rawBuild.getCauses()
于 2022-02-11T06:45:16.260 回答