ChatGPT解决这个技术问题 Extra ChatGPT

运行 shell 脚本时如何在 Jenkins 中将构建标记为不稳定

在我正在进行的一个项目中,我们使用 shell 脚本来执行不同的任务。有些是运行 rsync 的 sh/bash 脚本,有些是 PHP 脚本。其中一个 PHP 脚本正在运行一些集成测试,这些测试输出到 JUnit XML、代码覆盖率报告等。

Jenkins 能够根据 exit status 将作业标记为成功/失败。在 PHP 中,如果脚本在运行期间检测到测试失败,则脚本以 1 退出。其他 shell 脚本运行命令并使用其中的退出代码将构建标记为失败。

// :: End of PHP script:
// If any tests have failed, fail the build
if ($build_error) exit(1);

Jenkins Terminology 中,不稳定的构建定义为:

如果构建成功并且一个或多个发布者报告它不稳定,则构建是不稳定的。例如,如果配置了 JUnit 发布者并且测试失败,则构建将被标记为不稳定。

在运行 shell 脚本时,如何让 Jenkins 将构建标记为不稳定,而不仅仅是成功/失败?

我通过运行不同的工作步骤并使用 jenkins 插件实现了它stackoverflow.com/questions/25442343/…

A
Alan Franzoni

现代 Jenkins 版本(自 2016 年 10 月 2.26 起)解决了这个问题:它只是执行 shell 构建步骤的一个高级选项!

https://i.stack.imgur.com/2ZK2N.png

您可以选择并设置任意退出值;如果匹配,则构建将不稳定。只需选择一个不太可能由您的构建中的实际过程启动的值。


我喜欢这个选项,因为它不需要您安装任何额外的插件
由于这是在最新的 Jenkins 中实现的 - 这应该是一个公认的答案
“现代 Jenkins 版本”是指 Jenkins 2.26 或更新版本。请参阅issues.jenkins-ci.org/browse/JENKINS-23786
Jenkinsfile 中使用 sh 步骤命令时是否可以通过代码指定这一点?设置在 GUI 中的什么位置?我找不到它了。
我必须在构建步骤下单击打开“高级...”按钮才能公开它。在“单击此处执行操作”折叠器后面隐藏单个(并且不是特别高级)选项并不是很有用,但就是这样。
b
binaryLV

它可以在不打印魔术字符串和使用 TextFinder 的情况下完成。 Here's 关于它的一些信息。

基本上你需要一个来自 http://yourserver.com/cli 的 .jar 文件在 shell 脚本中可用,然后你可以使用下面的命令来标记一个不稳定的构建:

java -jar jenkins-cli.jar set-build-result unstable

要在错误上标记构建不稳定,您可以使用:

failing_cmd cmd_args || java -jar jenkins-cli.jar set-build-result unstable

问题是 jenkins-cli.jar 必须在 shell 脚本中可用。您可以将其放在易于访问的路径中,也可以通过作业的 shell 脚本下载:

wget ${JENKINS_URL}jnlpJars/jenkins-cli.jar

我真的很喜欢这个解决方案,我为此实现了一个 ruby 类,以便在我的 rakefile 中重用。 :)
+1 - 这是一个比接受的答案更好的解决方案,因为文本查找器每个作业只能搜索一个字符串,因此您只能将构建状态设置为两个值之一。
有趣的解决方案。但是,如果您的 Jenkins 需要身份验证,您将需要在其配置中设置公钥身份验证,否则任何 jenkins-cli 命令都会失败并出现 AccessDeniedException。
如果您使用的从属服务器无法访问主服务器,这将不起作用。例如,如果 Jenkins 从站无法创建返回服务器的 HTTP 或 HTTPS 连接。
我想使用此解决方案,但 set-build-resultjenkins-cli 中已被弃用。
J
Jan Hudec

使用 Text-finder 插件。

不要以状态 1 退出(这会使构建失败),而是:

if ($build_error) print("TESTS FAILED!");

在构建后操作中启用文本查找器,设置正则表达式以匹配您打印的消息 (TESTS FAILED!) 并选中该条目下的“如果找到则不稳定”复选框。


请参阅下面的答案以获取不安装插件的选项,因为 jenkins 版本 2.26:stackoverflow.com/a/49676269/1347649
p
poussma

您应该使用 Jenkinsfile 来包装您的构建脚本,并使用 currentBuild.result = "UNSTABLE" 简单地将当前构建标记为 UNSTABLE。

stage {
      status = /* your build command goes here */
      if (status === "MARK-AS-UNSTABLE") {
        currentBuild.result = "UNSTABLE"
      }
   }

为什么这个答案没有更多的赞成票?它有什么问题吗(除了使用“魔术”字符串UNSTABLE)?它似乎比其他答案更直接。
问题是关于自由式工作,而这个答案是关于管道工作。管道答案不适用于自由式工作
这甚至是如何工作的?当我尝试直接在阶段内设置 currentBuild.result 时出现错误:Expected one of "steps", "stages", or "parallel" for stage
K
Kalpesh Soni

您还应该能够使用 groovy 并执行 textfinder 所做的事情

marking a build as un-stable with groovy post-build plugin

if(manager.logContains("Could not login to FTP server")) {
    manager.addWarningBadge("FTP Login Failure")
    manager.createSummary("warning.gif").appendText("<h1>Failed to login to remote FTP Server!</h1>", false, false, false, "red")
    manager.buildUnstable()
}

另见Groovy Postbuild Plugin


s
sorin

在我的作业脚本中,我有以下语句(此作业仅在 Jenkins 主机上运行):

# This is the condition test I use to set the build status as UNSTABLE
if [ ${PERCENTAGE} -gt 80 -a ${PERCENTAGE} -lt 90 ]; then
  echo WARNING: disc usage percentage above 80%

  # Download the Jenkins CLI JAR:
  curl -o jenkins-cli.jar ${JENKINS_URL}/jnlpJars/jenkins-cli.jar

  # Set build status to unstable
  java -jar jenkins-cli.jar -s ${JENKINS_URL}/ set-build-result unstable

fi

您可以在 Jenkins wiki 上查看此内容以及有关设置构建状态的更多信息:https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+CLI


M
MariuszS

配置 PHP 构建以生成 xml junit 报告 .... 完成构建脚本,状态为 0 ... exit 0;为测试报告 XML 添加构建后操作发布 JUnit 测试结果报告。当测试失败时,此插件会将稳定版本更改为不稳定。 **/build/junit.xml 添加带有控制台输出扫描和未选中选项的 Jenkins Text Finder 插件。此插件因致命错误而导致整个构建失败。 PHP致命错误:


g
gib

here 复制我的答案,因为我花了一些时间寻找这个:

这现在可以在较新版本的 Jenkins 中实现,您可以执行以下操作:

#!/usr/bin/env groovy

properties([
  parameters([string(name: 'foo', defaultValue: 'bar', description: 'Fails job if not bar (unstable if bar)')]),
])


stage('Stage 1') {
  node('parent'){
    def ret = sh(
      returnStatus: true, // This is the key bit!
      script: '''if [ "$foo" = bar ]; then exit 2; else exit 1; fi'''
    )
    // ret can be any number/range, does not have to be 2.
    if (ret == 2) {
      currentBuild.result = 'UNSTABLE'
    } else if (ret != 0) {
      currentBuild.result = 'FAILURE'
      // If you do not manually error the status will be set to "failed", but the
      // pipeline will still run the next stage.
      error("Stage 1 failed with exit code ${ret}")
    }
  }
}

管道语法生成器在高级选项卡中向您显示:

https://i.stack.imgur.com/VxoSe.png


j
jeremyjjbrown

https://i.stack.imgur.com/YEK0u.png

import hudson.FilePath
import java.io.InputStream

def build = Thread.currentThread().executable

String unstable = null
if(build.workspace.isRemote()) {
    channel = build.workspace.channel;
    fp = new FilePath(channel, build.workspace.toString() + "/build.properties")
    InputStream is = fp.read()
    unstable = is.text.trim()
} else {
    fp = new FilePath(new File(build.workspace.toString() + "/build.properties"))
    InputStream is = fp.read()
    unstable = is.text.trim()
}

manager.listener.logger.println("Build status file: " + unstable)
if (unstable.equalsIgnoreCase('true')) {
    manager.listener.logger.println('setting build to unstable')
    manager.buildUnstable()
}

如果文件内容为“真”,则构建将设置为不稳定。这将适用于本地主机和运行作业的任何从机,以及任何可以写入磁盘的脚本。


我假设这真的说“如果工作区中有一个名为 build.properties 的文件”标记为不稳定。那正确吗?我是 Groovy 的新手,你介意再解释一下吗?
@uchuugaka 是的,如果有一个文件并且它具有这些内容。文件名和内容是任意的。使用任何适合您的情况。
谢谢!非常有帮助。 Groovy Postbuild 是相当间接的,Groovy 从 Java 中吸取了如此大量的东西并添加了更多……这对我来说是一个新技巧。
@uchuugaka 我认为这不是 groovy 的问题 :)
根本不是问题。只是一个挑战!
y
yorammi

仅当作业状态未从 SUCCESS 更改为 FAILED 或 ABORTED 时,TextFinder 才有效。对于这种情况,请在 PostBuild 步骤中使用 groovy 脚本:

errpattern = ~/TEXT-TO-LOOK-FOR-IN-JENKINS-BUILD-OUTPUT.*/;
manager.build.logFile.eachLine{ line ->
    errmatcher=errpattern.matcher(line)
    if (errmatcher.find()) {
        manager.build.@result = hudson.model.Result.NEW-STATUS-TO-SET
    }
 }

在我写的一篇文章中查看更多详细信息:http://www.tikalk.com/devops/JenkinsJobStatusChange/


a
adprocas

我想我会为可能正在寻找类似东西的人发布另一个答案。

在我们的构建工作中,我们希望构建继续进行,但被标记为不稳定。对于我们来说,它与版本号有关。

因此,我想在构建上设置一个条件,如果满足该条件,则将构建设置为不稳定。

我使用 Conditional step (single) 选项作为构建步骤。

然后,我使用 Execute system Groovy 脚本作为构建步骤,在满足该条件时运行。

我使用了 Groovy 命令并将脚本设置为以下

import hudson.model.*

def build = Thread.currentThread().executable
build.@result = hudson.model.Result.UNSTABLE

return

这似乎工作得很好。

我在这里偶然发现了解决方案

http://tech.akom.net/archives/112-Marking-Jenkins-build-UNSTABLE-from-environment-inject-groovy-script.html


K
Kaz

除了所有其他答案之外,jenkins 还允许使用 unstable() 方法(我认为这更清楚)。此方法可以与描述构建不稳定原因的消息参数一起使用。

除此之外,您可以使用 shell 脚本(bat 或 sh)的 returnStatus 来启用它。

例如:

def status = bat(script: "<your command here>", returnStatus: true)
if (status != 0) {
    unstable("unstable build because script failed")
}

当然,您可以根据您的需求和退货状态制作更精细的东西。

此外,为了引发错误,您还可以使用 warnError() 代替 unstable()。它将指示您的构建失败而不是不稳定,但语法相同。


A
Alex O

作为现有答案的更轻松替代方案,您可以使用简单的 HTTP POST 设置构建结果以访问 Groovy 脚本控制台 REST API:

    curl -X POST \
     --silent \
     --user "$YOUR_CREDENTIALS" \
     --data-urlencode "script=Jenkins.instance.getItemByFullName( '$JOB_NAME' ).getBuildByNumber( $BUILD_NUMBER ).setResult( hudson.model.Result.UNSTABLE )" $JENKINS_URL/scriptText

优点:

无需下载和运行巨大的 jar 文件

设置和读取一些全局状态(控制台文本,工作区中的文件)

不需要插件(除了 Groovy)

无需配置在 PASSED 或 FAILURE 情况下多余的额外构建步骤。

对于此解决方案,您的环境必须满足以下条件:

Jenkins REST API 可以从 slave 访问

从站必须有权访问允许访问 Jenkins Groovy 脚本 REST API 的凭据。


u
user1415664

将构建设置为不稳定的一种简单方法是在“执行 shell”块中运行 exit 13


据我所知,让 sh 运行以状态代码 13 退出的东西只会导致构建失败。
j
jessebs

您可以只调用“exit 1”,构建将在那时失败并且不会继续。我最终制作了一个直通 make 函数来为我处理它,并调用 safemake 而不是 make 进行构建:

function safemake {
  make "$@"
  if [ "$?" -ne 0 ]; then
    echo "ERROR: BUILD FAILED"
    exit 1
  else
    echo "BUILD SUCCEEDED"
  fi
}

出口 1,据我所知只会使构建失败。我不希望构建失败,我希望它被标记为不稳定。
另请参阅 stackoverflow.com/questions/36313216/… - 简单的解决方案就是 if make "$@"; then echo "BUILD SUCCEEDED"; else rc=$?; echo "BUILD FAILED"; exit $rc; fi